blob: bb41ce2b01bffa6785b270894b7fafdb80cfbbce [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>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000048
Roland McGrath134813a2007-06-02 00:07:33 +000049#ifdef LINUX
50# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
60#endif
61
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062#if defined(IA64) && defined(LINUX)
63# include <asm/ptrace_offsets.h>
64#endif
65
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000066#ifdef USE_PROCFS
67#include <poll.h>
68#endif
69
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#ifdef SVR4
71#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000072#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000073#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000074#include <sys/uio.h>
75#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000077#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000078extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000079extern int optind;
80extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000081
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082
Roland McGrath41c48222008-07-18 00:25:10 +000083int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020084unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020085/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020086static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000087int dtime = 0, xflag = 0, qflag = 0;
88cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000089static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000090/*
91 * daemonized_tracer supports -D option.
92 * With this option, strace forks twice.
93 * Unlike normal case, with -D *grandparent* process exec's,
94 * becoming a traced process. Child exits (this prevents traced process
95 * from having children it doesn't expect to have), and grandchild
96 * attaches to grandparent similarly to strace -p PID.
97 * This allows for more transparent interaction in cases
98 * when process and its parent are communicating via signals,
99 * wait() etc. Without -D, strace process gets lodged in between,
100 * disrupting parent<->child link.
101 */
102static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000104/* Sometimes we want to print only succeeding syscalls. */
105int not_failing_only = 0;
106
Grant Edwards8a082772011-04-07 20:25:40 +0000107/* Show path associated with fd arguments */
108int show_fd_path = 0;
109
110/* are we filtering traces based on paths? */
111int tracing_paths = 0;
112
Dmitry V. Levina6809652008-11-10 17:14:58 +0000113static int exit_code = 0;
114static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200115static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700116
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000117static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200118static uid_t run_uid;
119static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200122static int acolumn = DEFAULT_ACOLUMN;
123static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000124static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200125static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100126static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200128static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200129static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Andreas Schwabe5355de2009-10-27 16:56:43 +0100131static int detach(struct tcb *tcp, int sig);
132static int trace(void);
133static void cleanup(void);
134static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135static sigset_t empty_set, blocked_set;
136
137#ifdef HAVE_SIG_ATOMIC_T
138static volatile sig_atomic_t interrupted;
139#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141#endif /* !HAVE_SIG_ATOMIC_T */
142
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000143#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144
Andreas Schwabe5355de2009-10-27 16:56:43 +0100145static struct tcb *pfd2tcb(int pfd);
146static void reaper(int sig);
147static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000148static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
150#ifndef HAVE_POLLABLE_PROCFS
151
Andreas Schwabe5355de2009-10-27 16:56:43 +0100152static void proc_poll_open(void);
153static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
155struct proc_pollfd {
156 int fd;
157 int revents;
158 int pid;
159};
160
161static int poller_pid;
162static int proc_poll_pipe[2] = { -1, -1 };
163
164#endif /* !HAVE_POLLABLE_PROCFS */
165
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000166#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000167#define POLLWANT POLLWRNORM
168#else
169#define POLLWANT POLLPRI
170#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000171#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172
173static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200174usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175{
176 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000177usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000178 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000179 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200180 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000181 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200183-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-f -- follow forks, -ff -- with output into separate files\n\
185-F -- attempt to follow vforks, -h -- print help message\n\
186-i -- print instruction pointer at time of syscall\n\
187-q -- suppress messages about attaching, detaching, etc.\n\
188-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
189-T -- print time spent in each syscall, -V -- print version\n\
190-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
191-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000192-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193-a column -- alignment COLUMN for printing syscall results (default %d)\n\
194-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
195 options: trace, abbrev, verbose, raw, signal, read, or write\n\
196-o file -- send trace output to FILE instead of stderr\n\
197-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
198-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000199-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
201-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
202-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000203-E var=val -- put var=val in the environment for command\n\
204-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000205-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000206" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000207-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208 */
209, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210 exit(exitval);
211}
212
Denys Vlasenko75422762011-05-27 14:36:01 +0200213static void die(void) __attribute__ ((noreturn));
214static void die(void)
215{
216 if (strace_tracer_pid == getpid()) {
217 cflag = 0;
218 cleanup();
219 }
220 exit(1);
221}
222
223static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200224{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000225 fflush(NULL);
226 fprintf(stderr, "%s: ", progname);
227 vfprintf(stderr, fmt, p);
228 if (err_no)
229 fprintf(stderr, ": %s\n", strerror(err_no));
230 else
231 putc('\n', stderr);
232 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200233}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200234
Denys Vlasenko75422762011-05-27 14:36:01 +0200235void error_msg(const char *fmt, ...)
236{
237 va_list p;
238 va_start(p, fmt);
239 verror_msg(0, fmt, p);
240 va_end(p);
241}
242
243void error_msg_and_die(const char *fmt, ...)
244{
245 va_list p;
246 va_start(p, fmt);
247 verror_msg(0, fmt, p);
248 die();
249}
250
251void perror_msg(const char *fmt, ...)
252{
253 va_list p;
254 va_start(p, fmt);
255 verror_msg(errno, fmt, p);
256 va_end(p);
257}
258
259void perror_msg_and_die(const char *fmt, ...)
260{
261 va_list p;
262 va_start(p, fmt);
263 verror_msg(errno, fmt, p);
264 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200265}
266
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267#ifdef SVR4
268#ifdef MIPS
269void
270foobar()
271{
272}
273#endif /* MIPS */
274#endif /* SVR4 */
275
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400276/* Glue for systems without a MMU that cannot provide fork() */
277#ifdef HAVE_FORK
278# define strace_vforked 0
279#else
280# define strace_vforked 1
281# define fork() vfork()
282#endif
283
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200284static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000285set_cloexec_flag(int fd)
286{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200287 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000288
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200289 flags = fcntl(fd, F_GETFD);
290 if (flags < 0) {
291 /* Can happen only if fd is bad.
292 * Should never happen: if it does, we have a bug
293 * in the caller. Therefore we just abort
294 * instead of propagating the error.
295 */
296 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000297 }
298
299 newflags = flags | FD_CLOEXEC;
300 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200301 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000302
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200303 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000304}
305
306/*
307 * When strace is setuid executable, we have to swap uids
308 * before and after filesystem and process management operations.
309 */
310static void
311swap_uid(void)
312{
313#ifndef SVR4
314 int euid = geteuid(), uid = getuid();
315
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200316 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200317 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318 }
319#endif
320}
321
Roland McGrath4bfa6262007-07-05 20:03:16 +0000322#if _LFS64_LARGEFILE
323# define fopen_for_output fopen64
324#else
325# define fopen_for_output fopen
326#endif
327
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200329strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330{
331 FILE *fp;
332
333 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200334 fp = fopen_for_output(path, "w");
335 if (!fp)
336 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000337 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200338 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000339 return fp;
340}
341
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200342static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343
344#ifndef _PATH_BSHELL
345# define _PATH_BSHELL "/bin/sh"
346#endif
347
348/*
349 * We cannot use standard popen(3) here because we have to distinguish
350 * popen child process from other processes we trace, and standard popen(3)
351 * does not export its child's pid.
352 */
353static FILE *
354strace_popen(const char *command)
355{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200356 FILE *fp;
357 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000358
359 swap_uid();
360 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200361 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200363 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000364
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200365 popen_pid = vfork();
366 if (popen_pid == -1)
367 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000368
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200369 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370 /* child */
371 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200372 if (fds[0] != 0) {
373 if (dup2(fds[0], 0))
374 perror_msg_and_die("dup2");
375 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376 }
377 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200378 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000379 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200380
381 /* parent */
382 close(fds[0]);
383 swap_uid();
384 fp = fdopen(fds[1], "w");
385 if (!fp)
386 error_msg_and_die("Out of memory");
387 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388}
389
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200390static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391newoutf(struct tcb *tcp)
392{
393 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000394 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000395 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200396 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398}
399
Roland McGrath02203312007-06-11 22:06:31 +0000400static void
401startup_attach(void)
402{
403 int tcbi;
404 struct tcb *tcp;
405
406 /*
407 * Block user interruptions as we would leave the traced
408 * process stopped (process state T) if we would terminate in
409 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200410 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000411 */
412 if (interactive)
413 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
414
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000415 if (daemonized_tracer) {
416 pid_t pid = fork();
417 if (pid < 0) {
418 _exit(1);
419 }
420 if (pid) { /* parent */
421 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200422 * Wait for grandchild to attach to straced process
423 * (grandparent). Grandchild SIGKILLs us after it attached.
424 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000425 * it proceeds to exec the straced program.
426 */
427 pause();
428 _exit(0); /* paranoia */
429 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200430 /* grandchild */
431 /* We will be the tracer process. Remember our new pid: */
432 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000433 }
434
Roland McGrath02203312007-06-11 22:06:31 +0000435 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
436 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200437
Roland McGrath02203312007-06-11 22:06:31 +0000438 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
439 continue;
440#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200441 if (tcp->flags & TCB_ATTACH_DONE)
Roland McGrath02203312007-06-11 22:06:31 +0000442 continue;
443#endif
444 /* Reinitialize the output since it may have changed. */
445 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200446 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000447
448#ifdef USE_PROCFS
449 if (proc_open(tcp, 1) < 0) {
450 fprintf(stderr, "trouble opening proc file\n");
451 droptcb(tcp);
452 continue;
453 }
454#else /* !USE_PROCFS */
455# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000456 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000457 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000458 DIR *dir;
459
460 sprintf(procdir, "/proc/%d/task", tcp->pid);
461 dir = opendir(procdir);
462 if (dir != NULL) {
463 unsigned int ntid = 0, nerr = 0;
464 struct dirent *de;
465 int tid;
466 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000467 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000468 continue;
469 tid = atoi(de->d_name);
470 if (tid <= 0)
471 continue;
472 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200473 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000474 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200475 if (debug)
476 fprintf(stderr, "attach to pid %d failed\n", tid);
477 }
478 else {
479 if (debug)
480 fprintf(stderr, "attach to pid %d succeeded\n", tid);
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200481 if (tid != tcp->pid) {
482 struct tcb *new_tcp = alloctcb(tid);
483 new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200484 }
Roland McGrath02203312007-06-11 22:06:31 +0000485 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000486 if (interactive) {
487 sigprocmask(SIG_SETMASK, &empty_set, NULL);
488 if (interrupted)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200489 goto ret;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000490 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
491 }
Roland McGrath02203312007-06-11 22:06:31 +0000492 }
493 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000494 ntid -= nerr;
495 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000496 perror("attach: ptrace(PTRACE_ATTACH, ...)");
497 droptcb(tcp);
498 continue;
499 }
500 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000501 fprintf(stderr, ntid > 1
502? "Process %u attached with %u threads - interrupt to quit\n"
503: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200504 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000505 }
506 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000507 } /* if (opendir worked) */
508 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200509# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000510 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
511 perror("attach: ptrace(PTRACE_ATTACH, ...)");
512 droptcb(tcp);
513 continue;
514 }
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200515 if (debug)
516 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000517
518 if (daemonized_tracer) {
519 /*
520 * It is our grandparent we trace, not a -p PID.
521 * Don't want to just detach on exit, so...
522 */
523 tcp->flags &= ~TCB_ATTACHED;
524 /*
525 * Make parent go away.
526 * Also makes grandparent's wait() unblock.
527 */
528 kill(getppid(), SIGKILL);
529 }
530
Roland McGrath02203312007-06-11 22:06:31 +0000531#endif /* !USE_PROCFS */
532 if (!qflag)
533 fprintf(stderr,
534 "Process %u attached - interrupt to quit\n",
535 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200536 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000537
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200538 ret:
539#ifdef LINUX
540 /* TCB_ATTACH_DONE flag is used only in this function */
541 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
542 tcp = tcbtab[tcbi];
543 tcp->flags &= ~TCB_ATTACH_DONE;
544 }
545#endif
546
Roland McGrath02203312007-06-11 22:06:31 +0000547 if (interactive)
548 sigprocmask(SIG_SETMASK, &empty_set, NULL);
549}
550
551static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200552startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000553{
554 struct stat statbuf;
555 const char *filename;
556 char pathname[MAXPATHLEN];
557 int pid = 0;
558 struct tcb *tcp;
559
560 filename = argv[0];
561 if (strchr(filename, '/')) {
562 if (strlen(filename) > sizeof pathname - 1) {
563 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200564 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000565 }
566 strcpy(pathname, filename);
567 }
568#ifdef USE_DEBUGGING_EXEC
569 /*
570 * Debuggers customarily check the current directory
571 * first regardless of the path but doing that gives
572 * security geeks a panic attack.
573 */
574 else if (stat(filename, &statbuf) == 0)
575 strcpy(pathname, filename);
576#endif /* USE_DEBUGGING_EXEC */
577 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000578 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000579 int m, n, len;
580
581 for (path = getenv("PATH"); path && *path; path += m) {
582 if (strchr(path, ':')) {
583 n = strchr(path, ':') - path;
584 m = n + 1;
585 }
586 else
587 m = n = strlen(path);
588 if (n == 0) {
589 if (!getcwd(pathname, MAXPATHLEN))
590 continue;
591 len = strlen(pathname);
592 }
593 else if (n > sizeof pathname - 1)
594 continue;
595 else {
596 strncpy(pathname, path, n);
597 len = n;
598 }
599 if (len && pathname[len - 1] != '/')
600 pathname[len++] = '/';
601 strcpy(pathname + len, filename);
602 if (stat(pathname, &statbuf) == 0 &&
603 /* Accept only regular files
604 with some execute bits set.
605 XXX not perfect, might still fail */
606 S_ISREG(statbuf.st_mode) &&
607 (statbuf.st_mode & 0111))
608 break;
609 }
610 }
611 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200612 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000613 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000614 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000615 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200616 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000617 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200618 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
619 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000620 ) {
621 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000622#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200623 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000624#ifdef MIPS
625 /* Kludge for SGI, see proc_open for details. */
626 sa.sa_handler = foobar;
627 sa.sa_flags = 0;
628 sigemptyset(&sa.sa_mask);
629 sigaction(SIGINT, &sa, NULL);
630#endif /* MIPS */
631#ifndef FREEBSD
632 pause();
633#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000634 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000635#endif /* FREEBSD */
636#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200637 if (outf != stderr)
638 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000639
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000640 if (!daemonized_tracer) {
641 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200642 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000643 }
644 if (debug)
645 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000646 }
Roland McGrath02203312007-06-11 22:06:31 +0000647
648 if (username != NULL || geteuid() == 0) {
649 uid_t run_euid = run_uid;
650 gid_t run_egid = run_gid;
651
652 if (statbuf.st_mode & S_ISUID)
653 run_euid = statbuf.st_uid;
654 if (statbuf.st_mode & S_ISGID)
655 run_egid = statbuf.st_gid;
656
657 /*
658 * It is important to set groups before we
659 * lose privileges on setuid.
660 */
661 if (username != NULL) {
662 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200663 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000664 }
665 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200666 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000667 }
668 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200669 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000670 }
671 }
672 }
673 else
674 setreuid(run_uid, run_uid);
675
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000676 if (!daemonized_tracer) {
677 /*
678 * Induce an immediate stop so that the parent
679 * will resume us with PTRACE_SYSCALL and display
680 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400681 * Unless of course we're on a no-MMU system where
682 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000683 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400684 if (!strace_vforked)
685 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000686 } else {
687 struct sigaction sv_sigchld;
688 sigaction(SIGCHLD, NULL, &sv_sigchld);
689 /*
690 * Make sure it is not SIG_IGN, otherwise wait
691 * will not block.
692 */
693 signal(SIGCHLD, SIG_DFL);
694 /*
695 * Wait for grandchild to attach to us.
696 * It kills child after that, and wait() unblocks.
697 */
698 alarm(3);
699 wait(NULL);
700 alarm(0);
701 sigaction(SIGCHLD, &sv_sigchld, NULL);
702 }
Roland McGrath02203312007-06-11 22:06:31 +0000703#endif /* !USE_PROCFS */
704
705 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200706 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000707 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000708
709 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200710 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
711 strace_tracer_pid = getpid();
712
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000713 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 if (daemonized_tracer) {
715 /* We want subsequent startup_attach() to attach to it. */
716 tcp->flags |= TCB_ATTACHED;
717 }
Roland McGrath02203312007-06-11 22:06:31 +0000718#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200720 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000721 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000723}
724
Wang Chaob13c0de2010-11-12 17:25:19 +0800725#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000726static void kill_save_errno(pid_t pid, int sig)
727{
728 int saved_errno = errno;
729
730 (void) kill(pid, sig);
731 errno = saved_errno;
732}
733
Wang Chaob13c0de2010-11-12 17:25:19 +0800734/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000735 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800736 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000737 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800738 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000739static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200740test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800741{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000742 int pid, expected_grandchild = 0, found_grandchild = 0;
743 const unsigned int test_options = PTRACE_O_TRACECLONE |
744 PTRACE_O_TRACEFORK |
745 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800746
Denys Vlasenko5d645812011-08-20 12:48:18 +0200747 pid = fork();
748 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000749 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200750 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000751 pid = getpid();
752 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
753 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
754 __func__);
755 kill(pid, SIGSTOP);
756 if (fork() < 0)
757 perror_msg_and_die("fork");
758 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800759 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000760
761 while (1) {
762 int status, tracee_pid;
763
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000764 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000765 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000766 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000767 if (errno == EINTR)
768 continue;
769 else if (errno == ECHILD)
770 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000771 kill_save_errno(pid, SIGKILL);
772 perror_msg_and_die("%s: unexpected wait result %d",
773 __func__, tracee_pid);
774 }
775 if (WIFEXITED(status)) {
776 if (WEXITSTATUS(status)) {
777 if (tracee_pid != pid)
778 kill_save_errno(pid, SIGKILL);
779 error_msg_and_die("%s: unexpected exit status %u",
780 __func__, WEXITSTATUS(status));
781 }
782 continue;
783 }
784 if (WIFSIGNALED(status)) {
785 if (tracee_pid != pid)
786 kill_save_errno(pid, SIGKILL);
787 error_msg_and_die("%s: unexpected signal %u",
788 __func__, WTERMSIG(status));
789 }
790 if (!WIFSTOPPED(status)) {
791 if (tracee_pid != pid)
792 kill_save_errno(tracee_pid, SIGKILL);
793 kill(pid, SIGKILL);
794 error_msg_and_die("%s: unexpected wait status %x",
795 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000796 }
797 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000798 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000799 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
800 kill_save_errno(tracee_pid, SIGKILL);
801 kill_save_errno(pid, SIGKILL);
802 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800803 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000804 continue;
805 }
806 switch (WSTOPSIG(status)) {
807 case SIGSTOP:
808 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
809 && errno != EINVAL && errno != EIO)
810 perror_msg("PTRACE_SETOPTIONS");
811 break;
812 case SIGTRAP:
813 if (status >> 16 == PTRACE_EVENT_FORK) {
814 long msg = 0;
815
816 if (ptrace(PTRACE_GETEVENTMSG, pid,
817 NULL, (long) &msg) == 0)
818 expected_grandchild = msg;
819 }
820 break;
821 }
822 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
823 kill_save_errno(pid, SIGKILL);
824 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800825 }
826 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000827 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200828 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000829 if (debug)
830 fprintf(stderr, "ptrace_setoptions = %#x\n",
831 ptrace_setoptions);
832 return;
833 }
834 error_msg("Test for PTRACE_O_TRACECLONE failed, "
835 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800836}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200837
838/*
839 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
840 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
841 * and then see whether it will stop with (SIGTRAP | 0x80).
842 *
843 * Use of this option enables correct handling of user-generated SIGTRAPs,
844 * and SIGTRAPs generated by special instructions such as int3 on x86:
845 * _start: .globl _start
846 * int3
847 * movl $42, %ebx
848 * movl $1, %eax
849 * int $0x80
850 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
851 */
852static void
853test_ptrace_setoptions_for_all(void)
854{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000855 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
856 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200857 int pid;
858 int it_worked = 0;
859
860 pid = fork();
861 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200862 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200863
864 if (pid == 0) {
865 pid = getpid();
866 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200867 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000868 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
869 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200870 kill(pid, SIGSTOP);
871 _exit(0); /* parent should see entry into this syscall */
872 }
873
874 while (1) {
875 int status, tracee_pid;
876
877 errno = 0;
878 tracee_pid = wait(&status);
879 if (tracee_pid <= 0) {
880 if (errno == EINTR)
881 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000882 kill_save_errno(pid, SIGKILL);
883 perror_msg_and_die("%s: unexpected wait result %d",
884 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200885 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200886 if (WIFEXITED(status)) {
887 if (WEXITSTATUS(status) == 0)
888 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000889 error_msg_and_die("%s: unexpected exit status %u",
890 __func__, WEXITSTATUS(status));
891 }
892 if (WIFSIGNALED(status)) {
893 error_msg_and_die("%s: unexpected signal %u",
894 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200895 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200896 if (!WIFSTOPPED(status)) {
897 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000898 error_msg_and_die("%s: unexpected wait status %x",
899 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200900 }
901 if (WSTOPSIG(status) == SIGSTOP) {
902 /*
903 * We don't check "options aren't accepted" error.
904 * If it happens, we'll never get (SIGTRAP | 0x80),
905 * and thus will decide to not use the option.
906 * IOW: the outcome of the test will be correct.
907 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000908 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
909 && errno != EINVAL && errno != EIO)
910 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200911 }
912 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
913 it_worked = 1;
914 }
915 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000916 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200917 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200918 }
919 }
920
921 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200922 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200923 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200924 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200925 fprintf(stderr, "ptrace_setoptions = %#x\n",
926 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200927 return;
928 }
929
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000930 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
931 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200932}
Wang Chaob13c0de2010-11-12 17:25:19 +0800933#endif
934
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000936main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938 struct tcb *tcp;
939 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000940 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 struct sigaction sa;
942
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000943 progname = argv[0] ? argv[0] : "strace";
944
Denys Vlasenko75422762011-05-27 14:36:01 +0200945 strace_tracer_pid = getpid();
946
Roland McGrathee9d4352002-12-18 04:16:10 +0000947 /* Allocate the initial tcbtab. */
948 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200949 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200950 if (tcbtab == NULL)
951 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200952 tcp = calloc(tcbtabsize, sizeof(*tcp));
953 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200954 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200955 for (c = 0; c < tcbtabsize; c++)
956 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000957
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 outf = stderr;
959 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000960 set_sortby(DEFAULT_SORTBY);
961 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962 qualify("trace=all");
963 qualify("abbrev=all");
964 qualify("verbose=all");
965 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000967 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000968#ifndef USE_PROCFS
969 "D"
970#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000971 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 switch (c) {
973 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000974 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200975 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000976 }
977 cflag = CFLAG_ONLY_STATS;
978 break;
979 case 'C':
980 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200981 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000982 }
983 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 break;
985 case 'd':
986 debug++;
987 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000988#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000989 case 'D':
990 daemonized_tracer = 1;
991 break;
992#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000993 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000994 optF = 1;
995 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 case 'f':
997 followfork++;
998 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 case 'h':
1000 usage(stdout, 0);
1001 break;
1002 case 'i':
1003 iflag++;
1004 break;
1005 case 'q':
1006 qflag++;
1007 break;
1008 case 'r':
1009 rflag++;
1010 tflag++;
1011 break;
1012 case 't':
1013 tflag++;
1014 break;
1015 case 'T':
1016 dtime++;
1017 break;
1018 case 'x':
1019 xflag++;
1020 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001021 case 'y':
1022 show_fd_path = 1;
1023 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 case 'v':
1025 qualify("abbrev=none");
1026 break;
1027 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001028 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 exit(0);
1030 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001031 case 'z':
1032 not_failing_only = 1;
1033 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 case 'a':
1035 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001036 if (acolumn < 0)
1037 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 break;
1039 case 'e':
1040 qualify(optarg);
1041 break;
1042 case 'o':
1043 outfname = strdup(optarg);
1044 break;
1045 case 'O':
1046 set_overhead(atoi(optarg));
1047 break;
1048 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001049 pid = atoi(optarg);
1050 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001051 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 break;
1053 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001054 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001055 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 break;
1057 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001058 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001059 tcp->flags |= TCB_ATTACHED;
1060 pflag_seen++;
1061 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001062 case 'P':
1063 tracing_paths = 1;
1064 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001065 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001066 }
1067 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068 case 's':
1069 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001070 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001071 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001072 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 break;
1074 case 'S':
1075 set_sortby(optarg);
1076 break;
1077 case 'u':
1078 username = strdup(optarg);
1079 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001080 case 'E':
1081 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001082 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001083 }
1084 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085 default:
1086 usage(stderr, 1);
1087 break;
1088 }
1089 }
1090
Denys Vlasenko102ec492011-08-25 01:27:59 +02001091 acolumn_spaces = malloc(acolumn + 1);
1092 if (!acolumn_spaces)
1093 error_msg_and_die("Out of memory");
1094 memset(acolumn_spaces, ' ', acolumn);
1095 acolumn_spaces[acolumn] = '\0';
1096
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001097 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001098 usage(stderr, 1);
1099
Wang Chaod322a4b2010-08-05 14:30:11 +08001100 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001101 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001102 }
1103
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001104 if (!followfork)
1105 followfork = optF;
1106
Roland McGrathcb9def62006-04-25 07:48:03 +00001107 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001108 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001109 }
1110
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111 /* See if they want to run as another user. */
1112 if (username != NULL) {
1113 struct passwd *pent;
1114
1115 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001116 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001118 pent = getpwnam(username);
1119 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001120 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121 }
1122 run_uid = pent->pw_uid;
1123 run_gid = pent->pw_gid;
1124 }
1125 else {
1126 run_uid = getuid();
1127 run_gid = getgid();
1128 }
1129
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001130#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001131 if (followfork)
1132 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001133 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001134#endif
1135
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 /* Check if they want to redirect the output. */
1137 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001138 /* See if they want to pipe the output. */
1139 if (outfname[0] == '|' || outfname[0] == '!') {
1140 /*
1141 * We can't do the <outfname>.PID funny business
1142 * when using popen, so prohibit it.
1143 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001144 if (followfork > 1)
1145 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1146 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001147 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001148 else if (followfork <= 1)
1149 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 }
1151
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001152 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1153 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001155 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001156 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001159 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001160
Roland McGrath54cc1c82007-11-03 23:34:11 +00001161 /* Valid states here:
1162 optind < argc pflag_seen outfname interactive
1163 1 0 0 1
1164 0 1 0 1
1165 1 0 1 0
1166 0 1 1 1
1167 */
1168
1169 /* STARTUP_CHILD must be called before the signal handlers get
1170 installed below as they are inherited into the spawned process.
1171 Also we do not need to be protected by them as during interruption
1172 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1173 if (!pflag_seen)
1174 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 sigemptyset(&empty_set);
1177 sigemptyset(&blocked_set);
1178 sa.sa_handler = SIG_IGN;
1179 sigemptyset(&sa.sa_mask);
1180 sa.sa_flags = 0;
1181 sigaction(SIGTTOU, &sa, NULL);
1182 sigaction(SIGTTIN, &sa, NULL);
1183 if (interactive) {
1184 sigaddset(&blocked_set, SIGHUP);
1185 sigaddset(&blocked_set, SIGINT);
1186 sigaddset(&blocked_set, SIGQUIT);
1187 sigaddset(&blocked_set, SIGPIPE);
1188 sigaddset(&blocked_set, SIGTERM);
1189 sa.sa_handler = interrupt;
1190#ifdef SUNOS4
1191 /* POSIX signals on sunos4.1 are a little broken. */
1192 sa.sa_flags = SA_INTERRUPT;
1193#endif /* SUNOS4 */
1194 }
1195 sigaction(SIGHUP, &sa, NULL);
1196 sigaction(SIGINT, &sa, NULL);
1197 sigaction(SIGQUIT, &sa, NULL);
1198 sigaction(SIGPIPE, &sa, NULL);
1199 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001200#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 sa.sa_handler = reaper;
1202 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001203#else
1204 /* Make sure SIGCHLD has the default action so that waitpid
1205 definitely works without losing track of children. The user
1206 should not have given us a bogus state to inherit, but he might
1207 have. Arguably we should detect SIG_IGN here and pass it on
1208 to children, but probably noone really needs that. */
1209 sa.sa_handler = SIG_DFL;
1210 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001211#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001213 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001214 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001215
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 if (trace() < 0)
1217 exit(1);
1218 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001219 fflush(NULL);
1220 if (exit_code > 0xff) {
1221 /* Child was killed by a signal, mimic that. */
1222 exit_code &= 0xff;
1223 signal(exit_code, SIG_DFL);
1224 raise(exit_code);
1225 /* Paranoia - what if this signal is not fatal?
1226 Exit with 128 + signo then. */
1227 exit_code += 128;
1228 }
1229 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230}
1231
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001232static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001233expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001234{
1235 /* Allocate some more TCBs and expand the table.
1236 We don't want to relocate the TCBs because our
1237 callers have pointers and it would be a pain.
1238 So tcbtab is a table of pointers. Since we never
1239 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001240 int i = tcbtabsize;
1241 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1242 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1243 if (newtab == NULL || newtcbs == NULL)
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001244 error_msg_and_die("Out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001245 tcbtabsize *= 2;
1246 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001247 while (i < tcbtabsize)
1248 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001249}
1250
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001252alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001253{
1254 int i;
1255 struct tcb *tcp;
1256
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001257 if (nprocs == tcbtabsize)
1258 expand_tcbtab();
1259
Roland McGrathee9d4352002-12-18 04:16:10 +00001260 for (i = 0; i < tcbtabsize; i++) {
1261 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001263 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 tcp->flags = TCB_INUSE | TCB_STARTUP;
1266 tcp->outf = outf; /* Initialise to current out file */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001267#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001268 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001269#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001271 if (debug)
1272 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001273 if (command_options_parsed)
1274 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001275 return tcp;
1276 }
1277 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001278 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279}
1280
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001281#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001283proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284{
1285 char proc[32];
1286 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001287#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001288 int i;
1289 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290 sigset_t signals;
1291 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293#ifndef HAVE_POLLABLE_PROCFS
1294 static int last_pfd;
1295#endif
1296
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001297#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001298 /* Open the process pseudo-files in /proc. */
1299 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001300 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1301 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302 perror("strace: open(\"/proc/...\", ...)");
1303 return -1;
1304 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001305 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001306 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001307 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1308 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001309 perror("strace: open(\"/proc/...\", ...)");
1310 return -1;
1311 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001312 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001313 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001314 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1315 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001316 perror("strace: open(\"/proc/...\", ...)");
1317 return -1;
1318 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001319 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001320#else
1321 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001322# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001323 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001324 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001325# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001326 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001327 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001328# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001329 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001330 perror("strace: open(\"/proc/...\", ...)");
1331 return -1;
1332 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001333 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001334#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001335#ifdef FREEBSD
1336 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001337 tcp->pfd_reg = open(proc, O_RDONLY);
1338 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001339 perror("strace: open(\"/proc/.../regs\", ...)");
1340 return -1;
1341 }
1342 if (cflag) {
1343 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001344 tcp->pfd_status = open(proc, O_RDONLY);
1345 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001346 perror("strace: open(\"/proc/.../status\", ...)");
1347 return -1;
1348 }
1349 } else
1350 tcp->pfd_status = -1;
1351#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001352 rebuild_pollv();
1353 if (!attaching) {
1354 /*
1355 * Wait for the child to pause. Because of a race
1356 * condition we have to poll for the event.
1357 */
1358 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001359 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001360 perror("strace: PIOCSTATUS");
1361 return -1;
1362 }
1363 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001364 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001365 }
1366 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001367#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001368 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001369 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001370 perror("strace: PIOCSTOP");
1371 return -1;
1372 }
Roland McGrath553a6092002-12-16 20:40:39 +00001373#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374#ifdef PIOCSET
1375 /* Set Run-on-Last-Close. */
1376 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 perror("PIOCSET PR_RLC");
1379 return -1;
1380 }
1381 /* Set or Reset Inherit-on-Fork. */
1382 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 perror("PIOC{SET,RESET} PR_FORK");
1385 return -1;
1386 }
1387#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001388#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1390 perror("PIOCSRLC");
1391 return -1;
1392 }
1393 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1394 perror("PIOC{S,R}FORK");
1395 return -1;
1396 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001397#else /* FREEBSD */
1398 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1399 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1400 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001401 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001402 }
1403 arg &= ~PF_LINGER;
1404 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001405 perror("PIOCSFL");
1406 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001407 }
1408#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001410#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001411 /* Enable all syscall entries we care about. */
1412 premptyset(&syscalls);
1413 for (i = 1; i < MAX_QUALS; ++i) {
1414 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001415 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001416 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001417 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001418 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001419 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001420#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001421 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001422#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001423#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001424 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001425#endif
1426#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001427 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001428#endif
1429#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001430 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001431#endif
1432 }
1433 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434 perror("PIOCSENTRY");
1435 return -1;
1436 }
John Hughes19e49982001-10-19 08:59:12 +00001437 /* Enable the syscall exits. */
1438 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439 perror("PIOSEXIT");
1440 return -1;
1441 }
John Hughes19e49982001-10-19 08:59:12 +00001442 /* Enable signals we care about. */
1443 premptyset(&signals);
1444 for (i = 1; i < MAX_QUALS; ++i) {
1445 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001446 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001447 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001448 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 perror("PIOCSTRACE");
1450 return -1;
1451 }
John Hughes19e49982001-10-19 08:59:12 +00001452 /* Enable faults we care about */
1453 premptyset(&faults);
1454 for (i = 1; i < MAX_QUALS; ++i) {
1455 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001456 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001457 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001458 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 perror("PIOCSFAULT");
1460 return -1;
1461 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001462#else /* FREEBSD */
1463 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001464 arg = S_SIG | S_SCE | S_SCX;
1465 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001466 perror("PIOCBIS");
1467 return -1;
1468 }
1469#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470 if (!attaching) {
1471#ifdef MIPS
1472 /*
1473 * The SGI PRSABORT doesn't work for pause() so
1474 * we send it a caught signal to wake it up.
1475 */
1476 kill(tcp->pid, SIGINT);
1477#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001478#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001480 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001481 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 perror("PIOCRUN");
1483 return -1;
1484 }
Roland McGrath553a6092002-12-16 20:40:39 +00001485#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001486#endif /* !MIPS*/
1487#ifdef FREEBSD
1488 /* wake up the child if it received the SIGSTOP */
1489 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001490#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491 for (;;) {
1492 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001493 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 perror("PIOCWSTOP");
1495 return -1;
1496 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001497 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001498 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001499 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001500 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 break;
1502 }
1503 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001504#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001505 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001506 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1507#else
1508 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1509#endif
1510 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511 perror("PIOCRUN");
1512 return -1;
1513 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001514#ifdef FREEBSD
1515 /* handle the case where we "opened" the child before
1516 it did the kill -STOP */
1517 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1518 tcp->status.PR_WHAT == SIGSTOP)
1519 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001520#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521 }
1522 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001523#ifdef FREEBSD
1524 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001525 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001526 /* We are attaching to an already running process.
1527 * Try to figure out the state of the process in syscalls,
1528 * to handle the first event well.
1529 * This is done by having a look at the "wchan" property of the
1530 * process, which tells where it is stopped (if it is). */
1531 FILE * status;
1532 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001533
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001534 sprintf(proc, "/proc/%d/status", tcp->pid);
1535 status = fopen(proc, "r");
1536 if (status &&
1537 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1538 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1539 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1540 strcmp(wchan, "stopevent")) {
1541 /* The process is asleep in the middle of a syscall.
1542 Fake the syscall entry event */
1543 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1544 tcp->status.PR_WHY = PR_SYSENTRY;
1545 trace_syscall(tcp);
1546 }
1547 if (status)
1548 fclose(status);
1549 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001550 }
1551#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552#ifndef HAVE_POLLABLE_PROCFS
1553 if (proc_poll_pipe[0] != -1)
1554 proc_poller(tcp->pfd);
1555 else if (nprocs > 1) {
1556 proc_poll_open();
1557 proc_poller(last_pfd);
1558 proc_poller(tcp->pfd);
1559 }
1560 last_pfd = tcp->pfd;
1561#endif /* !HAVE_POLLABLE_PROCFS */
1562 return 0;
1563}
1564
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001567struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001568pid2tcb(int pid)
1569{
1570 int i;
1571
1572 if (pid <= 0)
1573 return NULL;
1574
1575 for (i = 0; i < tcbtabsize; i++) {
1576 struct tcb *tcp = tcbtab[i];
1577 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1578 return tcp;
1579 }
1580
1581 return NULL;
1582}
1583
1584#ifdef USE_PROCFS
1585
1586static struct tcb *
1587first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588{
1589 int i;
1590 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001591 for (i = 0; i < tcbtabsize; i++) {
1592 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593 if (tcp->flags & TCB_INUSE)
1594 return tcp;
1595 }
1596 return NULL;
1597}
1598
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001600pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601{
1602 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603
Roland McGrathca16be82003-01-10 19:55:28 +00001604 for (i = 0; i < tcbtabsize; i++) {
1605 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606 if (tcp->pfd != pfd)
1607 continue;
1608 if (tcp->flags & TCB_INUSE)
1609 return tcp;
1610 }
1611 return NULL;
1612}
1613
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001614#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615
1616void
Denys Vlasenko12014262011-05-30 14:00:14 +02001617droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618{
1619 if (tcp->pid == 0)
1620 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001621
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001623 if (debug)
1624 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001625
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001626#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 if (tcp->pfd != -1) {
1628 close(tcp->pfd);
1629 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001630# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001631 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 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001639# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001640 tcp->flags = 0; /* rebuild_pollv needs it */
1641 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001643#endif
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
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001648 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649}
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 McGrathca16be82003-01-10 19:55:28 +00001662#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663
1664 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001665 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666
1667#ifdef LINUX
1668 /*
1669 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001670 * before detaching. Arghh. We go through hoops
1671 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001673#if defined(SPARC)
1674#undef PTRACE_DETACH
1675#define PTRACE_DETACH PTRACE_SUNDETACH
1676#endif
Roland McGrath02203312007-06-11 22:06:31 +00001677 /*
1678 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1679 * expected SIGSTOP. We must catch exactly one as otherwise the
1680 * detached process would be left stopped (process state T).
1681 */
1682 catch_sigstop = (tcp->flags & TCB_STARTUP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001683 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1684 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001686 }
1687 else if (errno != ESRCH) {
1688 /* Shouldn't happen. */
1689 perror("detach: ptrace(PTRACE_DETACH, ...)");
1690 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001691 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001692 if (errno != ESRCH)
1693 perror("detach: checking sanity");
1694 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001695 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001696 if (errno != ESRCH)
1697 perror("detach: stopping child");
1698 }
Roland McGrath02203312007-06-11 22:06:31 +00001699 else
1700 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001701 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001703#ifdef __WALL
1704 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1705 if (errno == ECHILD) /* Already gone. */
1706 break;
1707 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001708 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001709 break;
1710 }
1711#endif /* __WALL */
1712 /* No __WALL here. */
1713 if (waitpid(tcp->pid, &status, 0) < 0) {
1714 if (errno != ECHILD) {
1715 perror("detach: waiting");
1716 break;
1717 }
1718#ifdef __WCLONE
1719 /* If no processes, try clones. */
1720 if (wait4(tcp->pid, &status, __WCLONE,
1721 NULL) < 0) {
1722 if (errno != ECHILD)
1723 perror("detach: waiting");
1724 break;
1725 }
1726#endif /* __WCLONE */
1727 }
1728#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001729 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001730#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731 if (!WIFSTOPPED(status)) {
1732 /* Au revoir, mon ami. */
1733 break;
1734 }
1735 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001736 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 break;
1738 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001739 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001740 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001741 : WSTOPSIG(status));
1742 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001745 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001746#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747
1748#if defined(SUNOS4)
1749 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1750 if (sig && kill(tcp->pid, sig) < 0)
1751 perror("detach: kill");
1752 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001753 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754#endif /* SUNOS4 */
1755
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756 if (!qflag)
1757 fprintf(stderr, "Process %u detached\n", tcp->pid);
1758
1759 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001760
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761 return error;
1762}
1763
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001764#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001766static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767{
1768 int pid;
1769 int status;
1770
1771 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 }
1773}
1774
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001775#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001776
1777static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001778cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779{
1780 int i;
1781 struct tcb *tcp;
1782
Roland McGrathee9d4352002-12-18 04:16:10 +00001783 for (i = 0; i < tcbtabsize; i++) {
1784 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 if (!(tcp->flags & TCB_INUSE))
1786 continue;
1787 if (debug)
1788 fprintf(stderr,
1789 "cleanup: looking at pid %u\n", tcp->pid);
1790 if (tcp_last &&
1791 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001792 tprintf(" <unfinished ...>");
1793 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001794 }
1795 if (tcp->flags & TCB_ATTACHED)
1796 detach(tcp, 0);
1797 else {
1798 kill(tcp->pid, SIGCONT);
1799 kill(tcp->pid, SIGTERM);
1800 }
1801 }
1802 if (cflag)
1803 call_summary(outf);
1804}
1805
1806static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001807interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808{
1809 interrupted = 1;
1810}
1811
1812#ifndef HAVE_STRERROR
1813
Roland McGrath6d2b3492002-12-30 00:51:30 +00001814#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001815extern int sys_nerr;
1816extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001817#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818
1819const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001820strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821{
1822 static char buf[64];
1823
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001824 if (err_no < 1 || err_no >= sys_nerr) {
1825 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 return buf;
1827 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001828 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829}
1830
1831#endif /* HAVE_STERRROR */
1832
1833#ifndef HAVE_STRSIGNAL
1834
Roland McGrath8f474e02003-01-14 07:53:33 +00001835#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001836extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001838#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1839extern char *_sys_siglist[];
1840#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001841
1842const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001843strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844{
1845 static char buf[64];
1846
1847 if (sig < 1 || sig >= NSIG) {
1848 sprintf(buf, "Unknown signal %d", sig);
1849 return buf;
1850 }
1851#ifdef HAVE__SYS_SIGLIST
1852 return _sys_siglist[sig];
1853#else
1854 return sys_siglist[sig];
1855#endif
1856}
1857
1858#endif /* HAVE_STRSIGNAL */
1859
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001860#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861
1862static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001863rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864{
1865 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001867 free(pollv);
1868 pollv = malloc(nprocs * sizeof(pollv[0]));
Roland McGrathee9d4352002-12-18 04:16:10 +00001869 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001870 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001871 }
1872
Roland McGrathca16be82003-01-10 19:55:28 +00001873 for (i = j = 0; i < tcbtabsize; i++) {
1874 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 if (!(tcp->flags & TCB_INUSE))
1876 continue;
1877 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001878 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879 j++;
1880 }
1881 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001882 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 }
1884}
1885
1886#ifndef HAVE_POLLABLE_PROCFS
1887
1888static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001889proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001890{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891 int i;
1892
1893 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001894 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895 }
1896 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001897 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 }
1899}
1900
1901static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001902proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903{
1904 int i;
1905 int n;
1906 struct proc_pollfd pollinfo;
1907
Denys Vlasenko5d645812011-08-20 12:48:18 +02001908 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1909 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910 return n;
1911 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001912 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001913 }
1914 for (i = 0; i < nprocs; i++) {
1915 if (pollv[i].fd == pollinfo.fd)
1916 pollv[i].revents = pollinfo.revents;
1917 else
1918 pollv[i].revents = 0;
1919 }
1920 poller_pid = pollinfo.pid;
1921 return 1;
1922}
1923
1924static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001925wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926{
1927}
1928
1929static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001930proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931{
1932 struct proc_pollfd pollinfo;
1933 struct sigaction sa;
1934 sigset_t blocked_set, empty_set;
1935 int i;
1936 int n;
1937 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001938#ifdef FREEBSD
1939 struct procfs_status pfs;
1940#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001941
1942 switch (fork()) {
1943 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001944 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945 case 0:
1946 break;
1947 default:
1948 return;
1949 }
1950
1951 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1952 sa.sa_flags = 0;
1953 sigemptyset(&sa.sa_mask);
1954 sigaction(SIGHUP, &sa, NULL);
1955 sigaction(SIGINT, &sa, NULL);
1956 sigaction(SIGQUIT, &sa, NULL);
1957 sigaction(SIGPIPE, &sa, NULL);
1958 sigaction(SIGTERM, &sa, NULL);
1959 sa.sa_handler = wakeup_handler;
1960 sigaction(SIGUSR1, &sa, NULL);
1961 sigemptyset(&blocked_set);
1962 sigaddset(&blocked_set, SIGUSR1);
1963 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1964 sigemptyset(&empty_set);
1965
1966 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001967 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001968 }
1969 n = rl.rlim_cur;
1970 for (i = 0; i < n; i++) {
1971 if (i != pfd && i != proc_poll_pipe[1])
1972 close(i);
1973 }
1974
1975 pollinfo.fd = pfd;
1976 pollinfo.pid = getpid();
1977 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001978#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001979 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1980#else
1981 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1982#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001983 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001984 switch (errno) {
1985 case EINTR:
1986 continue;
1987 case EBADF:
1988 pollinfo.revents = POLLERR;
1989 break;
1990 case ENOENT:
1991 pollinfo.revents = POLLHUP;
1992 break;
1993 default:
1994 perror("proc_poller: PIOCWSTOP");
1995 }
1996 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1997 _exit(0);
1998 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001999 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2001 sigsuspend(&empty_set);
2002 }
2003}
2004
2005#endif /* !HAVE_POLLABLE_PROCFS */
2006
2007static int
2008choose_pfd()
2009{
2010 int i, j;
2011 struct tcb *tcp;
2012
2013 static int last;
2014
2015 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002016 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017 /*
2018 * The previous process is ready to run again. We'll
2019 * let it do so if it is currently in a syscall. This
2020 * heuristic improves the readability of the trace.
2021 */
2022 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002023 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 return pollv[last].fd;
2025 }
2026
2027 for (i = 0; i < nprocs; i++) {
2028 /* Let competing children run round robin. */
2029 j = (i + last + 1) % nprocs;
2030 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2031 tcp = pfd2tcb(pollv[j].fd);
2032 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002033 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 }
2035 droptcb(tcp);
2036 return -1;
2037 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002038 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039 last = j;
2040 return pollv[j].fd;
2041 }
2042 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002043 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044}
2045
2046static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002047trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002049#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002050 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002051#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052 struct tcb *tcp;
2053 int pfd;
2054 int what;
2055 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057
2058 for (;;) {
2059 if (interactive)
2060 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2061
2062 if (nprocs == 0)
2063 break;
2064
2065 switch (nprocs) {
2066 case 1:
2067#ifndef HAVE_POLLABLE_PROCFS
2068 if (proc_poll_pipe[0] == -1) {
2069#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002070 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002071 if (!tcp)
2072 continue;
2073 pfd = tcp->pfd;
2074 if (pfd == -1)
2075 continue;
2076 break;
2077#ifndef HAVE_POLLABLE_PROCFS
2078 }
2079 /* fall through ... */
2080#endif /* !HAVE_POLLABLE_PROCFS */
2081 default:
2082#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002083#ifdef POLL_HACK
2084 /* On some systems (e.g. UnixWare) we get too much ugly
2085 "unfinished..." stuff when multiple proceses are in
2086 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002087
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002088 if (in_syscall) {
2089 struct pollfd pv;
2090 tcp = in_syscall;
2091 in_syscall = NULL;
2092 pv.fd = tcp->pfd;
2093 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002094 what = poll(&pv, 1, 1);
2095 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002096 if (interrupted)
2097 return 0;
2098 continue;
2099 }
2100 else if (what == 1 && pv.revents & POLLWANT) {
2101 goto FOUND;
2102 }
2103 }
2104#endif
2105
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106 if (poll(pollv, nprocs, INFTIM) < 0) {
2107 if (interrupted)
2108 return 0;
2109 continue;
2110 }
2111#else /* !HAVE_POLLABLE_PROCFS */
2112 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2113 if (interrupted)
2114 return 0;
2115 continue;
2116 }
2117#endif /* !HAVE_POLLABLE_PROCFS */
2118 pfd = choose_pfd();
2119 if (pfd == -1)
2120 continue;
2121 break;
2122 }
2123
2124 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002125 tcp = pfd2tcb(pfd);
2126 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002127 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 }
John Hughesb6643082002-05-23 11:02:22 +00002129#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002130 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132 /* Get the status of the process. */
2133 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002134#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002135 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002136#else /* FREEBSD */
2137 /* Thanks to some scheduling mystery, the first poller
2138 sometimes waits for the already processed end of fork
2139 event. Doing a non blocking poll here solves the problem. */
2140 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002141 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002142 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002143 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002144#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002145 ioctl_errno = errno;
2146#ifndef HAVE_POLLABLE_PROCFS
2147 if (proc_poll_pipe[0] != -1) {
2148 if (ioctl_result < 0)
2149 kill(poller_pid, SIGKILL);
2150 else
2151 kill(poller_pid, SIGUSR1);
2152 }
2153#endif /* !HAVE_POLLABLE_PROCFS */
2154 }
2155 if (interrupted)
2156 return 0;
2157
2158 if (interactive)
2159 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2160
2161 if (ioctl_result < 0) {
2162 /* Find out what happened if it failed. */
2163 switch (ioctl_errno) {
2164 case EINTR:
2165 case EBADF:
2166 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002167#ifdef FREEBSD
2168 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002169#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002170 case ENOENT:
2171 droptcb(tcp);
2172 continue;
2173 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002174 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002175 }
2176 }
2177
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002178#ifdef FREEBSD
2179 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2180 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002181 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002182 continue;
2183 }
Roland McGrath553a6092002-12-16 20:40:39 +00002184#endif
2185
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002186 /* clear the just started flag */
2187 tcp->flags &= ~TCB_STARTUP;
2188
2189 /* set current output file */
2190 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002191 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002192
2193 if (cflag) {
2194 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002195#ifdef FREEBSD
2196 char buf[1024];
2197 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198
Denys Vlasenko5d645812011-08-20 12:48:18 +02002199 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2200 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002201 buf[len] = '\0';
2202 sscanf(buf,
2203 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2204 &stime.tv_sec, &stime.tv_usec);
2205 } else
2206 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002207#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2209 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002210#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2212 tcp->stime = stime;
2213 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002214 what = tcp->status.PR_WHAT;
2215 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002216#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002218 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2219 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002220 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002221 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002222 }
2223 }
2224 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002225#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002226 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002227#ifdef POLL_HACK
2228 in_syscall = tcp;
2229#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002230 case PR_SYSEXIT:
2231 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002232 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 }
2234 break;
2235 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002236 if (cflag != CFLAG_ONLY_STATS
2237 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002238 printleader(tcp);
2239 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002240 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002241 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002242#ifdef PR_INFO
2243 if (tcp->status.PR_INFO.si_signo == what) {
2244 printleader(tcp);
2245 tprintf(" siginfo=");
2246 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002247 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002248 }
2249#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002250 }
2251 break;
2252 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002253 if (cflag != CFLAGS_ONLY_STATS
2254 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002255 printleader(tcp);
2256 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002257 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002258 }
2259 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002260#ifdef FREEBSD
2261 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002262 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002265 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 break;
2267 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002268 /* Remember current print column before continuing. */
2269 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002270 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002271#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002272 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002273#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002274 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002275#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002276 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002277 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002278 }
2279 }
2280 return 0;
2281}
2282
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002283#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002284
Roland McGratheb9e2e82009-06-02 16:49:22 -07002285static int
2286trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287{
2288 int pid;
2289 int wait_errno;
2290 int status;
2291 struct tcb *tcp;
2292#ifdef LINUX
2293 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002294 struct rusage *rup = cflag ? &ru : NULL;
2295# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002296 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002297# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002298#endif /* LINUX */
2299
Roland McGratheb9e2e82009-06-02 16:49:22 -07002300 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002301 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002302 return 0;
2303 if (interactive)
2304 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002306# ifdef __WALL
2307 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002308 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002309 /* this kernel does not support __WALL */
2310 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002311 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002312 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002313 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002314 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002315 pid = wait4(-1, &status, __WCLONE, rup);
2316 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002317 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002318 }
2319 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002320# else
2321 pid = wait4(-1, &status, 0, rup);
2322# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323#endif /* LINUX */
2324#ifdef SUNOS4
2325 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002326#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002328 if (interactive)
2329 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002331 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002332 switch (wait_errno) {
2333 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002335 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 /*
2337 * We would like to verify this case
2338 * but sometimes a race in Solbourne's
2339 * version of SunOS sometimes reports
2340 * ECHILD before sending us SIGCHILD.
2341 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002342 return 0;
2343 default:
2344 errno = wait_errno;
2345 perror("strace: wait");
2346 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002347 }
2348 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002349 if (pid == popen_pid) {
2350 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002351 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002352 continue;
2353 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002354 if (debug) {
2355 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2356#ifdef LINUX
2357 unsigned ev = (unsigned)status >> 16;
2358 if (ev) {
2359 static const char *const event_names[] = {
2360 [PTRACE_EVENT_CLONE] = "CLONE",
2361 [PTRACE_EVENT_FORK] = "FORK",
2362 [PTRACE_EVENT_VFORK] = "VFORK",
2363 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2364 [PTRACE_EVENT_EXEC] = "EXEC",
2365 [PTRACE_EVENT_EXIT] = "EXIT",
2366 };
2367 const char *e;
2368 if (ev < ARRAY_SIZE(event_names))
2369 e = event_names[ev];
2370 else {
2371 sprintf(buf, "?? (%u)", ev);
2372 e = buf;
2373 }
2374 fprintf(stderr, " PTRACE_EVENT_%s", e);
2375 }
2376#endif
2377 strcpy(buf, "???");
2378 if (WIFSIGNALED(status))
2379#ifdef WCOREDUMP
2380 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2381 WCOREDUMP(status) ? "core," : "",
2382 signame(WTERMSIG(status)));
2383#else
2384 sprintf(buf, "WIFSIGNALED,sig=%s",
2385 signame(WTERMSIG(status)));
2386#endif
2387 if (WIFEXITED(status))
2388 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2389 if (WIFSTOPPED(status))
2390 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002391#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002392 if (WIFCONTINUED(status))
2393 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002394#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002395 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2396 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002397
2398 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002399 tcp = pid2tcb(pid);
2400 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002401#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002402 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002403 /* This is needed to go with the CLONE_PTRACE
2404 changes in process.c/util.c: we might see
2405 the child's initial trap before we see the
2406 parent return from the clone syscall.
2407 Leave the child suspended until the parent
2408 returns from its system call. Only then
2409 will we have the association of parent and
2410 child so that we know how to do clearbpt
2411 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002412 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002413 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002414 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002415 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002416 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002417 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002418 else
2419 /* This can happen if a clone call used
2420 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002421#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002422 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002423 if (WIFSTOPPED(status))
2424 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002425 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002426 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002427 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002428 /* set current output file */
2429 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002430 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002431#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002432 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002433 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2434 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002435 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002436#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002437
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002439 if (pid == strace_child)
2440 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002441 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002442 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2443 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002444#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002445 tprintf("+++ killed by %s %s+++",
2446 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002447 WCOREDUMP(status) ? "(core dumped) " : "");
2448#else
2449 tprintf("+++ killed by %s +++",
2450 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002451#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002452 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002453 }
2454 droptcb(tcp);
2455 continue;
2456 }
2457 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002458 if (pid == strace_child)
2459 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002460 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002461 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002462 tprintf(" <unfinished ... exit status %d>\n",
2463 WEXITSTATUS(status));
2464 tcp_last = NULL;
2465 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002466 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2467 printleader(tcp);
2468 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2469 printtrailer();
2470 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002471 droptcb(tcp);
2472 continue;
2473 }
2474 if (!WIFSTOPPED(status)) {
2475 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2476 droptcb(tcp);
2477 continue;
2478 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002479
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002480 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002481 /* Ptrace event (we ignore all of them for now) */
2482 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002483 }
2484
Roland McGrath02203312007-06-11 22:06:31 +00002485 /*
2486 * Interestingly, the process may stop
2487 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002488 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002489 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002490 * A no-MMU vforked child won't send up a signal,
2491 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002492 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002493 if ((tcp->flags & TCB_STARTUP) &&
2494 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002495 /*
2496 * This flag is there to keep us in sync.
2497 * Next time this process stops it should
2498 * really be entering a system call.
2499 */
2500 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002501 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002502 /*
2503 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002504 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002505 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002506 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2507 droptcb(tcp);
2508 cleanup();
2509 return -1;
2510 }
2511 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002512#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002513 if (ptrace_setoptions) {
2514 if (debug)
2515 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2516 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2517 if (errno != ESRCH) {
2518 /* Should never happen, really */
2519 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002520 }
2521 }
2522 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002523#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002524 goto tracing;
2525 }
2526
Denys Vlasenko75422762011-05-27 14:36:01 +02002527 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002528 if (WSTOPSIG(status) == SIGSTOP &&
2529 (tcp->flags & TCB_SIGTRAPPED)) {
2530 /*
2531 * Trapped attempt to block SIGTRAP
2532 * Hope we are back in control now.
2533 */
2534 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002535 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002536 cleanup();
2537 return -1;
2538 }
2539 continue;
2540 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002541 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002542 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002543 siginfo_t si;
2544#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002545 long pc = 0;
2546 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002547
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002548 upeek(tcp, PT_CR_IPSR, &psr);
2549 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002550
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002551# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002552 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002553# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002554# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002555#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002556# define PC_FORMAT_STR ""
2557# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002558#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002559 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002560 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2561 tprintf("--- ");
2562 printsiginfo(&si, verbose(tcp));
2563 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002564 strsignal(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002565 PC_FORMAT_ARG);
2566 } else
2567 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2568 strsignal(WSTOPSIG(status)),
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002569 signame(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002570 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002571 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002573 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002574 cleanup();
2575 return -1;
2576 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 continue;
2578 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002579
2580 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002581 if (interrupted)
2582 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002583
2584 /* This should be syscall entry or exit.
2585 * (Or it still can be that pesky post-execve SIGTRAP!)
2586 * Handle it.
2587 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002588 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2589 /* ptrace() failed in trace_syscall() with ESRCH.
2590 * Likely a result of process disappearing mid-flight.
2591 * Observed case: exit_group() terminating
2592 * all processes in thread group. In this case, threads
2593 * "disappear" in an unpredictable moment without any
2594 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002595 */
2596 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002597 if (tcp_last) {
2598 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002599 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002600 */
2601 tcp_last->flags |= TCB_REPRINT;
2602 tprintf(" <unfinished ...>");
2603 printtrailer();
2604 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002605 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002606 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 ptrace(PTRACE_KILL,
2608 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002609 droptcb(tcp);
2610 }
2611 continue;
2612 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002613 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002614 /* Remember current print column before continuing. */
2615 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002616 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002617 cleanup();
2618 return -1;
2619 }
2620 }
2621 return 0;
2622}
2623
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002624#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002626void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002628{
2629 va_list args;
2630
Andreas Schwabe5355de2009-10-27 16:56:43 +01002631 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002632 if (outf) {
2633 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002634 if (n < 0) {
2635 if (outf != stderr)
2636 perror(outfname == NULL
2637 ? "<writing to pipe>" : outfname);
2638 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002639 curcol += n;
2640 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002641 va_end(args);
2642 return;
2643}
2644
2645void
Denys Vlasenko12014262011-05-30 14:00:14 +02002646printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002647{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002648 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002649 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002650 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002651 tprintf(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002652 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002653 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002654 tprintf("= ? <unavailable>\n");
2655 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002656 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002657 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002658 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002659 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002660 }
2661 curcol = 0;
2662 if ((followfork == 1 || pflag_seen > 1) && outfname)
2663 tprintf("%-5d ", tcp->pid);
2664 else if (nprocs > 1 && !outfname)
2665 tprintf("[pid %5u] ", tcp->pid);
2666 if (tflag) {
2667 char str[sizeof("HH:MM:SS")];
2668 struct timeval tv, dtv;
2669 static struct timeval otv;
2670
2671 gettimeofday(&tv, NULL);
2672 if (rflag) {
2673 if (otv.tv_sec == 0)
2674 otv = tv;
2675 tv_sub(&dtv, &tv, &otv);
2676 tprintf("%6ld.%06ld ",
2677 (long) dtv.tv_sec, (long) dtv.tv_usec);
2678 otv = tv;
2679 }
2680 else if (tflag > 2) {
2681 tprintf("%ld.%06ld ",
2682 (long) tv.tv_sec, (long) tv.tv_usec);
2683 }
2684 else {
2685 time_t local = tv.tv_sec;
2686 strftime(str, sizeof(str), "%T", localtime(&local));
2687 if (tflag > 1)
2688 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2689 else
2690 tprintf("%s ", str);
2691 }
2692 }
2693 if (iflag)
2694 printcall(tcp);
2695}
2696
2697void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002698tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002700 if (curcol < acolumn)
2701 tprintf(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002702}
2703
2704void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002705printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706{
2707 tprintf("\n");
2708 tcp_last = NULL;
2709}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002710
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002711#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002712
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002713int
2714mp_ioctl(int fd, int cmd, void *arg, int size)
2715{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002716 struct iovec iov[2];
2717 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002718
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002719 iov[0].iov_base = &cmd;
2720 iov[0].iov_len = sizeof cmd;
2721 if (arg) {
2722 ++n;
2723 iov[1].iov_base = arg;
2724 iov[1].iov_len = size;
2725 }
Roland McGrath553a6092002-12-16 20:40:39 +00002726
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002727 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002728}
2729
2730#endif