blob: 02324f70aa657784e266c1bcafa48766e6fd3299 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
John Hughes19e49982001-10-19 08:59:12 +000047#include <limits.h>
Roland McGrath70b08532004-04-09 00:25:21 +000048#include <dirent.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050#ifdef LINUX
51# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020052# if defined __NR_tkill
53# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000054# else
55 /* kill() may choose arbitrarily the target task of the process group
56 while we later wait on a that specific TID. PID process waits become
57 TID task specific waits for a process under ptrace(2). */
58# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020059# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000060# endif
61#endif
62
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000063#if defined(IA64) && defined(LINUX)
64# include <asm/ptrace_offsets.h>
65#endif
66
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +000067#ifdef USE_PROCFS
68#include <poll.h>
69#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071#ifdef SVR4
72#include <sys/stropts.h>
Wichert Akkermanea78f0f1999-11-29 15:34:02 +000073#ifdef HAVE_MP_PROCFS
John Hughes1d08dcf2001-07-10 13:48:44 +000074#ifdef HAVE_SYS_UIO_H
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000075#include <sys/uio.h>
76#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
John Hughes1d08dcf2001-07-10 13:48:44 +000078#endif
Denys Vlasenko96d5a762008-12-29 19:13:27 +000079extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000080extern int optind;
81extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000082
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083
Roland McGrath41c48222008-07-18 00:25:10 +000084int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020085unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020086/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020087static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000088int dtime = 0, xflag = 0, qflag = 0;
89cflag_t cflag = CFLAG_NONE;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +000090static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000105/* Sometimes we want to print only succeeding syscalls. */
106int not_failing_only = 0;
107
Grant Edwards8a082772011-04-07 20:25:40 +0000108/* Show path associated with fd arguments */
109int show_fd_path = 0;
110
111/* are we filtering traces based on paths? */
112int tracing_paths = 0;
113
Dmitry V. Levina6809652008-11-10 17:14:58 +0000114static int exit_code = 0;
115static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200116static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700117
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000118static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200119static uid_t run_uid;
120static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200123static int acolumn = DEFAULT_ACOLUMN;
124static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000125static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200126static FILE *outf;
Andreas Schwabccdff482009-10-27 16:27:13 +0100127static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200128static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200129static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
Andreas Schwabe5355de2009-10-27 16:56:43 +0100132static int detach(struct tcb *tcp, int sig);
133static int trace(void);
134static void cleanup(void);
135static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136static sigset_t empty_set, blocked_set;
137
138#ifdef HAVE_SIG_ATOMIC_T
139static volatile sig_atomic_t interrupted;
140#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142#endif /* !HAVE_SIG_ATOMIC_T */
143
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000144#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145
Andreas Schwabe5355de2009-10-27 16:56:43 +0100146static struct tcb *pfd2tcb(int pfd);
147static void reaper(int sig);
148static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000149static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150
151#ifndef HAVE_POLLABLE_PROCFS
152
Andreas Schwabe5355de2009-10-27 16:56:43 +0100153static void proc_poll_open(void);
154static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155
156struct proc_pollfd {
157 int fd;
158 int revents;
159 int pid;
160};
161
162static int poller_pid;
163static int proc_poll_pipe[2] = { -1, -1 };
164
165#endif /* !HAVE_POLLABLE_PROCFS */
166
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000167#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000168#define POLLWANT POLLWRNORM
169#else
170#define POLLWANT POLLPRI
171#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000172#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000173
174static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200175usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176{
177 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000178usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000179 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000180 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200181 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200184-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185-f -- follow forks, -ff -- with output into separate files\n\
186-F -- attempt to follow vforks, -h -- print help message\n\
187-i -- print instruction pointer at time of syscall\n\
188-q -- suppress messages about attaching, detaching, etc.\n\
189-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
190-T -- print time spent in each syscall, -V -- print version\n\
191-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
192-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000193-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194-a column -- alignment COLUMN for printing syscall results (default %d)\n\
195-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
196 options: trace, abbrev, verbose, raw, signal, read, or write\n\
197-o file -- send trace output to FILE instead of stderr\n\
198-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
199-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000200-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
202-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
203-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000204-E var=val -- put var=val in the environment for command\n\
205-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000206-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000207" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000208-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000209 */
210, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211 exit(exitval);
212}
213
Denys Vlasenko75422762011-05-27 14:36:01 +0200214static void die(void) __attribute__ ((noreturn));
215static void die(void)
216{
217 if (strace_tracer_pid == getpid()) {
218 cflag = 0;
219 cleanup();
220 }
221 exit(1);
222}
223
224static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200225{
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000226 fflush(NULL);
227 fprintf(stderr, "%s: ", progname);
228 vfprintf(stderr, fmt, p);
229 if (err_no)
230 fprintf(stderr, ": %s\n", strerror(err_no));
231 else
232 putc('\n', stderr);
233 fflush(stderr);
Denys Vlasenko75422762011-05-27 14:36:01 +0200234}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200235
Denys Vlasenko75422762011-05-27 14:36:01 +0200236void error_msg(const char *fmt, ...)
237{
238 va_list p;
239 va_start(p, fmt);
240 verror_msg(0, fmt, p);
241 va_end(p);
242}
243
244void error_msg_and_die(const char *fmt, ...)
245{
246 va_list p;
247 va_start(p, fmt);
248 verror_msg(0, fmt, p);
249 die();
250}
251
252void perror_msg(const char *fmt, ...)
253{
254 va_list p;
255 va_start(p, fmt);
256 verror_msg(errno, fmt, p);
257 va_end(p);
258}
259
260void perror_msg_and_die(const char *fmt, ...)
261{
262 va_list p;
263 va_start(p, fmt);
264 verror_msg(errno, fmt, p);
265 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200266}
267
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268#ifdef SVR4
269#ifdef MIPS
270void
271foobar()
272{
273}
274#endif /* MIPS */
275#endif /* SVR4 */
276
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400277/* Glue for systems without a MMU that cannot provide fork() */
278#ifdef HAVE_FORK
279# define strace_vforked 0
280#else
281# define strace_vforked 1
282# define fork() vfork()
283#endif
284
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200285static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000286set_cloexec_flag(int fd)
287{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200288 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000289
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200290 flags = fcntl(fd, F_GETFD);
291 if (flags < 0) {
292 /* Can happen only if fd is bad.
293 * Should never happen: if it does, we have a bug
294 * in the caller. Therefore we just abort
295 * instead of propagating the error.
296 */
297 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000298 }
299
300 newflags = flags | FD_CLOEXEC;
301 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200302 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000303
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200304 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000305}
306
307/*
308 * When strace is setuid executable, we have to swap uids
309 * before and after filesystem and process management operations.
310 */
311static void
312swap_uid(void)
313{
314#ifndef SVR4
315 int euid = geteuid(), uid = getuid();
316
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200317 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200318 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000319 }
320#endif
321}
322
Roland McGrath4bfa6262007-07-05 20:03:16 +0000323#if _LFS64_LARGEFILE
324# define fopen_for_output fopen64
325#else
326# define fopen_for_output fopen
327#endif
328
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000329static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200330strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000331{
332 FILE *fp;
333
334 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200335 fp = fopen_for_output(path, "w");
336 if (!fp)
337 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000338 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200339 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000340 return fp;
341}
342
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200343static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000344
345#ifndef _PATH_BSHELL
346# define _PATH_BSHELL "/bin/sh"
347#endif
348
349/*
350 * We cannot use standard popen(3) here because we have to distinguish
351 * popen child process from other processes we trace, and standard popen(3)
352 * does not export its child's pid.
353 */
354static FILE *
355strace_popen(const char *command)
356{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200357 FILE *fp;
358 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000359
360 swap_uid();
361 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200362 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000363
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200364 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000365
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200366 popen_pid = vfork();
367 if (popen_pid == -1)
368 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200370 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371 /* child */
372 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200373 if (fds[0] != 0) {
374 if (dup2(fds[0], 0))
375 perror_msg_and_die("dup2");
376 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000377 }
378 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200379 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000380 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200381
382 /* parent */
383 close(fds[0]);
384 swap_uid();
385 fp = fdopen(fds[1], "w");
386 if (!fp)
387 error_msg_and_die("Out of memory");
388 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000389}
390
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200391static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000392newoutf(struct tcb *tcp)
393{
394 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000395 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000396 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200397 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000398 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000399}
400
Roland McGrath02203312007-06-11 22:06:31 +0000401static void
402startup_attach(void)
403{
404 int tcbi;
405 struct tcb *tcp;
406
407 /*
408 * Block user interruptions as we would leave the traced
409 * process stopped (process state T) if we would terminate in
410 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200411 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000412 */
413 if (interactive)
414 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
415
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000416 if (daemonized_tracer) {
417 pid_t pid = fork();
418 if (pid < 0) {
419 _exit(1);
420 }
421 if (pid) { /* parent */
422 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200423 * Wait for grandchild to attach to straced process
424 * (grandparent). Grandchild SIGKILLs us after it attached.
425 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000426 * it proceeds to exec the straced program.
427 */
428 pause();
429 _exit(0); /* paranoia */
430 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200431 /* grandchild */
432 /* We will be the tracer process. Remember our new pid: */
433 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000434 }
435
Roland McGrath02203312007-06-11 22:06:31 +0000436 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
437 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200438
Roland McGrath02203312007-06-11 22:06:31 +0000439 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
440 continue;
441#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200442 if (tcp->flags & TCB_ATTACH_DONE)
Roland McGrath02203312007-06-11 22:06:31 +0000443 continue;
444#endif
445 /* Reinitialize the output since it may have changed. */
446 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200447 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000448
449#ifdef USE_PROCFS
450 if (proc_open(tcp, 1) < 0) {
451 fprintf(stderr, "trouble opening proc file\n");
452 droptcb(tcp);
453 continue;
454 }
455#else /* !USE_PROCFS */
456# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000457 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000458 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000459 DIR *dir;
460
461 sprintf(procdir, "/proc/%d/task", tcp->pid);
462 dir = opendir(procdir);
463 if (dir != NULL) {
464 unsigned int ntid = 0, nerr = 0;
465 struct dirent *de;
466 int tid;
467 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000468 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000469 continue;
470 tid = atoi(de->d_name);
471 if (tid <= 0)
472 continue;
473 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200474 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000475 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200476 if (debug)
477 fprintf(stderr, "attach to pid %d failed\n", tid);
478 }
479 else {
480 if (debug)
481 fprintf(stderr, "attach to pid %d succeeded\n", tid);
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200482 if (tid != tcp->pid) {
483 struct tcb *new_tcp = alloctcb(tid);
484 new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200485 }
Roland McGrath02203312007-06-11 22:06:31 +0000486 }
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000487 if (interactive) {
488 sigprocmask(SIG_SETMASK, &empty_set, NULL);
489 if (interrupted)
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200490 goto ret;
Denys Vlasenkoaab52ca2009-03-17 14:46:54 +0000491 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
492 }
Roland McGrath02203312007-06-11 22:06:31 +0000493 }
494 closedir(dir);
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000495 ntid -= nerr;
496 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000497 perror("attach: ptrace(PTRACE_ATTACH, ...)");
498 droptcb(tcp);
499 continue;
500 }
501 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000502 fprintf(stderr, ntid > 1
503? "Process %u attached with %u threads - interrupt to quit\n"
504: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200505 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000506 }
507 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000508 } /* if (opendir worked) */
509 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200510# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000511 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
512 perror("attach: ptrace(PTRACE_ATTACH, ...)");
513 droptcb(tcp);
514 continue;
515 }
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200516 if (debug)
517 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000518
519 if (daemonized_tracer) {
520 /*
521 * It is our grandparent we trace, not a -p PID.
522 * Don't want to just detach on exit, so...
523 */
524 tcp->flags &= ~TCB_ATTACHED;
525 /*
526 * Make parent go away.
527 * Also makes grandparent's wait() unblock.
528 */
529 kill(getppid(), SIGKILL);
530 }
531
Roland McGrath02203312007-06-11 22:06:31 +0000532#endif /* !USE_PROCFS */
533 if (!qflag)
534 fprintf(stderr,
535 "Process %u attached - interrupt to quit\n",
536 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200537 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000538
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200539 ret:
540#ifdef LINUX
541 /* TCB_ATTACH_DONE flag is used only in this function */
542 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
543 tcp = tcbtab[tcbi];
544 tcp->flags &= ~TCB_ATTACH_DONE;
545 }
546#endif
547
Roland McGrath02203312007-06-11 22:06:31 +0000548 if (interactive)
549 sigprocmask(SIG_SETMASK, &empty_set, NULL);
550}
551
552static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200553startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000554{
555 struct stat statbuf;
556 const char *filename;
557 char pathname[MAXPATHLEN];
558 int pid = 0;
559 struct tcb *tcp;
560
561 filename = argv[0];
562 if (strchr(filename, '/')) {
563 if (strlen(filename) > sizeof pathname - 1) {
564 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200565 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000566 }
567 strcpy(pathname, filename);
568 }
569#ifdef USE_DEBUGGING_EXEC
570 /*
571 * Debuggers customarily check the current directory
572 * first regardless of the path but doing that gives
573 * security geeks a panic attack.
574 */
575 else if (stat(filename, &statbuf) == 0)
576 strcpy(pathname, filename);
577#endif /* USE_DEBUGGING_EXEC */
578 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000579 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000580 int m, n, len;
581
582 for (path = getenv("PATH"); path && *path; path += m) {
583 if (strchr(path, ':')) {
584 n = strchr(path, ':') - path;
585 m = n + 1;
586 }
587 else
588 m = n = strlen(path);
589 if (n == 0) {
590 if (!getcwd(pathname, MAXPATHLEN))
591 continue;
592 len = strlen(pathname);
593 }
594 else if (n > sizeof pathname - 1)
595 continue;
596 else {
597 strncpy(pathname, path, n);
598 len = n;
599 }
600 if (len && pathname[len - 1] != '/')
601 pathname[len++] = '/';
602 strcpy(pathname + len, filename);
603 if (stat(pathname, &statbuf) == 0 &&
604 /* Accept only regular files
605 with some execute bits set.
606 XXX not perfect, might still fail */
607 S_ISREG(statbuf.st_mode) &&
608 (statbuf.st_mode & 0111))
609 break;
610 }
611 }
612 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200613 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000614 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000615 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000616 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200617 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000618 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200619 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
620 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000621 ) {
622 pid = getpid();
Roland McGrath02203312007-06-11 22:06:31 +0000623#ifdef USE_PROCFS
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200624 if (outf != stderr) close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000625#ifdef MIPS
626 /* Kludge for SGI, see proc_open for details. */
627 sa.sa_handler = foobar;
628 sa.sa_flags = 0;
629 sigemptyset(&sa.sa_mask);
630 sigaction(SIGINT, &sa, NULL);
631#endif /* MIPS */
632#ifndef FREEBSD
633 pause();
634#else /* FREEBSD */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000635 kill(pid, SIGSTOP); /* stop HERE */
Roland McGrath02203312007-06-11 22:06:31 +0000636#endif /* FREEBSD */
637#else /* !USE_PROCFS */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200638 if (outf != stderr)
639 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000640
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000641 if (!daemonized_tracer) {
642 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200643 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000644 }
645 if (debug)
646 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000647 }
Roland McGrath02203312007-06-11 22:06:31 +0000648
649 if (username != NULL || geteuid() == 0) {
650 uid_t run_euid = run_uid;
651 gid_t run_egid = run_gid;
652
653 if (statbuf.st_mode & S_ISUID)
654 run_euid = statbuf.st_uid;
655 if (statbuf.st_mode & S_ISGID)
656 run_egid = statbuf.st_gid;
657
658 /*
659 * It is important to set groups before we
660 * lose privileges on setuid.
661 */
662 if (username != NULL) {
663 if (initgroups(username, run_gid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200664 perror_msg_and_die("initgroups");
Roland McGrath02203312007-06-11 22:06:31 +0000665 }
666 if (setregid(run_gid, run_egid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200667 perror_msg_and_die("setregid");
Roland McGrath02203312007-06-11 22:06:31 +0000668 }
669 if (setreuid(run_uid, run_euid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200670 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000671 }
672 }
673 }
674 else
675 setreuid(run_uid, run_uid);
676
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 if (!daemonized_tracer) {
678 /*
679 * Induce an immediate stop so that the parent
680 * will resume us with PTRACE_SYSCALL and display
681 * this execve call normally.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400682 * Unless of course we're on a no-MMU system where
683 * we vfork()-ed, so we cannot stop the child.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000684 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400685 if (!strace_vforked)
686 kill(getpid(), SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000687 } else {
688 struct sigaction sv_sigchld;
689 sigaction(SIGCHLD, NULL, &sv_sigchld);
690 /*
691 * Make sure it is not SIG_IGN, otherwise wait
692 * will not block.
693 */
694 signal(SIGCHLD, SIG_DFL);
695 /*
696 * Wait for grandchild to attach to us.
697 * It kills child after that, and wait() unblocks.
698 */
699 alarm(3);
700 wait(NULL);
701 alarm(0);
702 sigaction(SIGCHLD, &sv_sigchld, NULL);
703 }
Roland McGrath02203312007-06-11 22:06:31 +0000704#endif /* !USE_PROCFS */
705
706 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200707 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000708 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000709
710 /* We are the tracer. */
Denys Vlasenko75422762011-05-27 14:36:01 +0200711 /* With -D, we are *child* here, IOW: different pid. Fetch it. */
712 strace_tracer_pid = getpid();
713
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 tcp = alloctcb(daemonized_tracer ? getppid() : pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715 if (daemonized_tracer) {
716 /* We want subsequent startup_attach() to attach to it. */
717 tcp->flags |= TCB_ATTACHED;
718 }
Roland McGrath02203312007-06-11 22:06:31 +0000719#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000720 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200721 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000722 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000723#endif /* USE_PROCFS */
Roland McGrath02203312007-06-11 22:06:31 +0000724}
725
Wang Chaob13c0de2010-11-12 17:25:19 +0800726#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000727static void kill_save_errno(pid_t pid, int sig)
728{
729 int saved_errno = errno;
730
731 (void) kill(pid, sig);
732 errno = saved_errno;
733}
734
Wang Chaob13c0de2010-11-12 17:25:19 +0800735/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000736 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800737 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000738 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800739 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000740static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200741test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800742{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000743 int pid, expected_grandchild = 0, found_grandchild = 0;
744 const unsigned int test_options = PTRACE_O_TRACECLONE |
745 PTRACE_O_TRACEFORK |
746 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800747
Denys Vlasenko5d645812011-08-20 12:48:18 +0200748 pid = fork();
749 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000750 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200751 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000752 pid = getpid();
753 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
754 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
755 __func__);
756 kill(pid, SIGSTOP);
757 if (fork() < 0)
758 perror_msg_and_die("fork");
759 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800760 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000761
762 while (1) {
763 int status, tracee_pid;
764
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000765 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000766 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000767 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000768 if (errno == EINTR)
769 continue;
770 else if (errno == ECHILD)
771 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000772 kill_save_errno(pid, SIGKILL);
773 perror_msg_and_die("%s: unexpected wait result %d",
774 __func__, tracee_pid);
775 }
776 if (WIFEXITED(status)) {
777 if (WEXITSTATUS(status)) {
778 if (tracee_pid != pid)
779 kill_save_errno(pid, SIGKILL);
780 error_msg_and_die("%s: unexpected exit status %u",
781 __func__, WEXITSTATUS(status));
782 }
783 continue;
784 }
785 if (WIFSIGNALED(status)) {
786 if (tracee_pid != pid)
787 kill_save_errno(pid, SIGKILL);
788 error_msg_and_die("%s: unexpected signal %u",
789 __func__, WTERMSIG(status));
790 }
791 if (!WIFSTOPPED(status)) {
792 if (tracee_pid != pid)
793 kill_save_errno(tracee_pid, SIGKILL);
794 kill(pid, SIGKILL);
795 error_msg_and_die("%s: unexpected wait status %x",
796 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000797 }
798 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000799 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000800 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
801 kill_save_errno(tracee_pid, SIGKILL);
802 kill_save_errno(pid, SIGKILL);
803 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800804 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000805 continue;
806 }
807 switch (WSTOPSIG(status)) {
808 case SIGSTOP:
809 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
810 && errno != EINVAL && errno != EIO)
811 perror_msg("PTRACE_SETOPTIONS");
812 break;
813 case SIGTRAP:
814 if (status >> 16 == PTRACE_EVENT_FORK) {
815 long msg = 0;
816
817 if (ptrace(PTRACE_GETEVENTMSG, pid,
818 NULL, (long) &msg) == 0)
819 expected_grandchild = msg;
820 }
821 break;
822 }
823 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
824 kill_save_errno(pid, SIGKILL);
825 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800826 }
827 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000828 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200829 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000830 if (debug)
831 fprintf(stderr, "ptrace_setoptions = %#x\n",
832 ptrace_setoptions);
833 return;
834 }
835 error_msg("Test for PTRACE_O_TRACECLONE failed, "
836 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800837}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200838
839/*
840 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
841 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
842 * and then see whether it will stop with (SIGTRAP | 0x80).
843 *
844 * Use of this option enables correct handling of user-generated SIGTRAPs,
845 * and SIGTRAPs generated by special instructions such as int3 on x86:
846 * _start: .globl _start
847 * int3
848 * movl $42, %ebx
849 * movl $1, %eax
850 * int $0x80
851 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
852 */
853static void
854test_ptrace_setoptions_for_all(void)
855{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000856 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
857 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200858 int pid;
859 int it_worked = 0;
860
861 pid = fork();
862 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200863 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200864
865 if (pid == 0) {
866 pid = getpid();
867 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200868 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000869 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
870 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200871 kill(pid, SIGSTOP);
872 _exit(0); /* parent should see entry into this syscall */
873 }
874
875 while (1) {
876 int status, tracee_pid;
877
878 errno = 0;
879 tracee_pid = wait(&status);
880 if (tracee_pid <= 0) {
881 if (errno == EINTR)
882 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000883 kill_save_errno(pid, SIGKILL);
884 perror_msg_and_die("%s: unexpected wait result %d",
885 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200886 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200887 if (WIFEXITED(status)) {
888 if (WEXITSTATUS(status) == 0)
889 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000890 error_msg_and_die("%s: unexpected exit status %u",
891 __func__, WEXITSTATUS(status));
892 }
893 if (WIFSIGNALED(status)) {
894 error_msg_and_die("%s: unexpected signal %u",
895 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200896 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200897 if (!WIFSTOPPED(status)) {
898 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000899 error_msg_and_die("%s: unexpected wait status %x",
900 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200901 }
902 if (WSTOPSIG(status) == SIGSTOP) {
903 /*
904 * We don't check "options aren't accepted" error.
905 * If it happens, we'll never get (SIGTRAP | 0x80),
906 * and thus will decide to not use the option.
907 * IOW: the outcome of the test will be correct.
908 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000909 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
910 && errno != EINVAL && errno != EIO)
911 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200912 }
913 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
914 it_worked = 1;
915 }
916 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000917 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200918 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200919 }
920 }
921
922 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200923 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200924 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200925 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200926 fprintf(stderr, "ptrace_setoptions = %#x\n",
927 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200928 return;
929 }
930
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000931 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
932 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200933}
Wang Chaob13c0de2010-11-12 17:25:19 +0800934#endif
935
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000936int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000937main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000938{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000939 struct tcb *tcp;
940 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000941 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 struct sigaction sa;
943
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000944 progname = argv[0] ? argv[0] : "strace";
945
Denys Vlasenko75422762011-05-27 14:36:01 +0200946 strace_tracer_pid = getpid();
947
Roland McGrathee9d4352002-12-18 04:16:10 +0000948 /* Allocate the initial tcbtab. */
949 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200950 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200951 if (tcbtab == NULL)
952 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200953 tcp = calloc(tcbtabsize, sizeof(*tcp));
954 if (tcp == NULL)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200955 error_msg_and_die("Out of memory");
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200956 for (c = 0; c < tcbtabsize; c++)
957 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +0000958
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 outf = stderr;
960 interactive = 1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000961 set_sortby(DEFAULT_SORTBY);
962 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 qualify("trace=all");
964 qualify("abbrev=all");
965 qualify("verbose=all");
966 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +0000968 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000969#ifndef USE_PROCFS
970 "D"
971#endif
Grant Edwards8a082772011-04-07 20:25:40 +0000972 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 switch (c) {
974 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000975 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200976 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000977 }
978 cflag = CFLAG_ONLY_STATS;
979 break;
980 case 'C':
981 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200982 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +0000983 }
984 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 break;
986 case 'd':
987 debug++;
988 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000989#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000990 case 'D':
991 daemonized_tracer = 1;
992 break;
993#endif
Roland McGrath41c48222008-07-18 00:25:10 +0000994 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000995 optF = 1;
996 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 case 'f':
998 followfork++;
999 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 case 'h':
1001 usage(stdout, 0);
1002 break;
1003 case 'i':
1004 iflag++;
1005 break;
1006 case 'q':
1007 qflag++;
1008 break;
1009 case 'r':
1010 rflag++;
1011 tflag++;
1012 break;
1013 case 't':
1014 tflag++;
1015 break;
1016 case 'T':
1017 dtime++;
1018 break;
1019 case 'x':
1020 xflag++;
1021 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001022 case 'y':
1023 show_fd_path = 1;
1024 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025 case 'v':
1026 qualify("abbrev=none");
1027 break;
1028 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001029 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030 exit(0);
1031 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001032 case 'z':
1033 not_failing_only = 1;
1034 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 case 'a':
1036 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001037 if (acolumn < 0)
1038 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 break;
1040 case 'e':
1041 qualify(optarg);
1042 break;
1043 case 'o':
1044 outfname = strdup(optarg);
1045 break;
1046 case 'O':
1047 set_overhead(atoi(optarg));
1048 break;
1049 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001050 pid = atoi(optarg);
1051 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001052 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 break;
1054 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001055 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001056 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 break;
1058 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001059 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 tcp->flags |= TCB_ATTACHED;
1061 pflag_seen++;
1062 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001063 case 'P':
1064 tracing_paths = 1;
1065 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001066 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001067 }
1068 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001069 case 's':
1070 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001071 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001072 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001073 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 break;
1075 case 'S':
1076 set_sortby(optarg);
1077 break;
1078 case 'u':
1079 username = strdup(optarg);
1080 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001081 case 'E':
1082 if (putenv(optarg) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001083 error_msg_and_die("Out of memory");
Roland McGrathde6e5332003-01-24 04:31:23 +00001084 }
1085 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086 default:
1087 usage(stderr, 1);
1088 break;
1089 }
1090 }
1091
Denys Vlasenko102ec492011-08-25 01:27:59 +02001092 acolumn_spaces = malloc(acolumn + 1);
1093 if (!acolumn_spaces)
1094 error_msg_and_die("Out of memory");
1095 memset(acolumn_spaces, ' ', acolumn);
1096 acolumn_spaces[acolumn] = '\0';
1097
Roland McGrathd0c4c0c2006-04-25 07:39:40 +00001098 if ((optind == argc) == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001099 usage(stderr, 1);
1100
Wang Chaod322a4b2010-08-05 14:30:11 +08001101 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001102 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001103 }
1104
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001105 if (!followfork)
1106 followfork = optF;
1107
Roland McGrathcb9def62006-04-25 07:48:03 +00001108 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001109 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001110 }
1111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 /* See if they want to run as another user. */
1113 if (username != NULL) {
1114 struct passwd *pent;
1115
1116 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001117 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001119 pent = getpwnam(username);
1120 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001121 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 }
1123 run_uid = pent->pw_uid;
1124 run_gid = pent->pw_gid;
1125 }
1126 else {
1127 run_uid = getuid();
1128 run_gid = getgid();
1129 }
1130
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001131#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001132 if (followfork)
1133 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001134 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001135#endif
1136
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 /* Check if they want to redirect the output. */
1138 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001139 /* See if they want to pipe the output. */
1140 if (outfname[0] == '|' || outfname[0] == '!') {
1141 /*
1142 * We can't do the <outfname>.PID funny business
1143 * when using popen, so prohibit it.
1144 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001145 if (followfork > 1)
1146 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1147 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001148 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001149 else if (followfork <= 1)
1150 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 }
1152
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001153 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1154 static char buf[BUFSIZ];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001156 }
Roland McGrath37b9a662003-11-07 02:26:54 +00001157 if (outfname && optind < argc) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001160 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001161
Roland McGrath54cc1c82007-11-03 23:34:11 +00001162 /* Valid states here:
1163 optind < argc pflag_seen outfname interactive
1164 1 0 0 1
1165 0 1 0 1
1166 1 0 1 0
1167 0 1 1 1
1168 */
1169
1170 /* STARTUP_CHILD must be called before the signal handlers get
1171 installed below as they are inherited into the spawned process.
1172 Also we do not need to be protected by them as during interruption
1173 in the STARTUP_CHILD mode we kill the spawned process anyway. */
1174 if (!pflag_seen)
1175 startup_child(&argv[optind]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 sigemptyset(&empty_set);
1178 sigemptyset(&blocked_set);
1179 sa.sa_handler = SIG_IGN;
1180 sigemptyset(&sa.sa_mask);
1181 sa.sa_flags = 0;
1182 sigaction(SIGTTOU, &sa, NULL);
1183 sigaction(SIGTTIN, &sa, NULL);
1184 if (interactive) {
1185 sigaddset(&blocked_set, SIGHUP);
1186 sigaddset(&blocked_set, SIGINT);
1187 sigaddset(&blocked_set, SIGQUIT);
1188 sigaddset(&blocked_set, SIGPIPE);
1189 sigaddset(&blocked_set, SIGTERM);
1190 sa.sa_handler = interrupt;
1191#ifdef SUNOS4
1192 /* POSIX signals on sunos4.1 are a little broken. */
1193 sa.sa_flags = SA_INTERRUPT;
1194#endif /* SUNOS4 */
1195 }
1196 sigaction(SIGHUP, &sa, NULL);
1197 sigaction(SIGINT, &sa, NULL);
1198 sigaction(SIGQUIT, &sa, NULL);
1199 sigaction(SIGPIPE, &sa, NULL);
1200 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001201#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 sa.sa_handler = reaper;
1203 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001204#else
1205 /* Make sure SIGCHLD has the default action so that waitpid
1206 definitely works without losing track of children. The user
1207 should not have given us a bogus state to inherit, but he might
1208 have. Arguably we should detect SIG_IGN here and pass it on
1209 to children, but probably noone really needs that. */
1210 sa.sa_handler = SIG_DFL;
1211 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001212#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001214 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001215 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001216
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 if (trace() < 0)
1218 exit(1);
1219 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001220 fflush(NULL);
1221 if (exit_code > 0xff) {
1222 /* Child was killed by a signal, mimic that. */
1223 exit_code &= 0xff;
1224 signal(exit_code, SIG_DFL);
1225 raise(exit_code);
1226 /* Paranoia - what if this signal is not fatal?
1227 Exit with 128 + signo then. */
1228 exit_code += 128;
1229 }
1230 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231}
1232
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001233static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001234expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001235{
1236 /* Allocate some more TCBs and expand the table.
1237 We don't want to relocate the TCBs because our
1238 callers have pointers and it would be a pain.
1239 So tcbtab is a table of pointers. Since we never
1240 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001241 int i = tcbtabsize;
1242 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1243 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
1244 if (newtab == NULL || newtcbs == NULL)
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001245 error_msg_and_die("Out of memory");
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001246 tcbtabsize *= 2;
1247 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001248 while (i < tcbtabsize)
1249 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001250}
1251
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001253alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001254{
1255 int i;
1256 struct tcb *tcp;
1257
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001258 if (nprocs == tcbtabsize)
1259 expand_tcbtab();
1260
Roland McGrathee9d4352002-12-18 04:16:10 +00001261 for (i = 0; i < tcbtabsize; i++) {
1262 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001264 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 tcp->pid = pid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001266 tcp->flags = TCB_INUSE | TCB_STARTUP;
1267 tcp->outf = outf; /* Initialise to current out file */
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001268#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001270#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001272 if (debug)
1273 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001274 if (command_options_parsed)
1275 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 return tcp;
1277 }
1278 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001279 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280}
1281
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001282#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001284proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285{
1286 char proc[32];
1287 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001288#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001289 int i;
1290 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291 sigset_t signals;
1292 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001293#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294#ifndef HAVE_POLLABLE_PROCFS
1295 static int last_pfd;
1296#endif
1297
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001298#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001299 /* Open the process pseudo-files in /proc. */
1300 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001301 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1302 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001303 perror("strace: open(\"/proc/...\", ...)");
1304 return -1;
1305 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001306 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001307 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001308 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1309 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001310 perror("strace: open(\"/proc/...\", ...)");
1311 return -1;
1312 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001313 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001314 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001315 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1316 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001317 perror("strace: open(\"/proc/...\", ...)");
1318 return -1;
1319 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001320 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001321#else
1322 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001323# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001324 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001325 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001326# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001327 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001328 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001329# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001330 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331 perror("strace: open(\"/proc/...\", ...)");
1332 return -1;
1333 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001334 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001335#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001336#ifdef FREEBSD
1337 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001338 tcp->pfd_reg = open(proc, O_RDONLY);
1339 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001340 perror("strace: open(\"/proc/.../regs\", ...)");
1341 return -1;
1342 }
1343 if (cflag) {
1344 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001345 tcp->pfd_status = open(proc, O_RDONLY);
1346 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001347 perror("strace: open(\"/proc/.../status\", ...)");
1348 return -1;
1349 }
1350 } else
1351 tcp->pfd_status = -1;
1352#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001353 rebuild_pollv();
1354 if (!attaching) {
1355 /*
1356 * Wait for the child to pause. Because of a race
1357 * condition we have to poll for the event.
1358 */
1359 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001360 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001361 perror("strace: PIOCSTATUS");
1362 return -1;
1363 }
1364 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001365 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001366 }
1367 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001368#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001369 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001370 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001371 perror("strace: PIOCSTOP");
1372 return -1;
1373 }
Roland McGrath553a6092002-12-16 20:40:39 +00001374#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375#ifdef PIOCSET
1376 /* Set Run-on-Last-Close. */
1377 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001378 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379 perror("PIOCSET PR_RLC");
1380 return -1;
1381 }
1382 /* Set or Reset Inherit-on-Fork. */
1383 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001384 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385 perror("PIOC{SET,RESET} PR_FORK");
1386 return -1;
1387 }
1388#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001389#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1391 perror("PIOCSRLC");
1392 return -1;
1393 }
1394 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1395 perror("PIOC{S,R}FORK");
1396 return -1;
1397 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001398#else /* FREEBSD */
1399 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1400 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1401 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001402 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001403 }
1404 arg &= ~PF_LINGER;
1405 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001406 perror("PIOCSFL");
1407 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001408 }
1409#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001411#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001412 /* Enable all syscall entries we care about. */
1413 premptyset(&syscalls);
1414 for (i = 1; i < MAX_QUALS; ++i) {
1415 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001416 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001417 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001418 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001419 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001420 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001421#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001422 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001423#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001424#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001425 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001426#endif
1427#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001428 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001429#endif
1430#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001431 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001432#endif
1433 }
1434 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435 perror("PIOCSENTRY");
1436 return -1;
1437 }
John Hughes19e49982001-10-19 08:59:12 +00001438 /* Enable the syscall exits. */
1439 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440 perror("PIOSEXIT");
1441 return -1;
1442 }
John Hughes19e49982001-10-19 08:59:12 +00001443 /* Enable signals we care about. */
1444 premptyset(&signals);
1445 for (i = 1; i < MAX_QUALS; ++i) {
1446 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001447 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001448 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001449 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 perror("PIOCSTRACE");
1451 return -1;
1452 }
John Hughes19e49982001-10-19 08:59:12 +00001453 /* Enable faults we care about */
1454 premptyset(&faults);
1455 for (i = 1; i < MAX_QUALS; ++i) {
1456 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001457 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001458 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001459 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460 perror("PIOCSFAULT");
1461 return -1;
1462 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001463#else /* FREEBSD */
1464 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001465 arg = S_SIG | S_SCE | S_SCX;
1466 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001467 perror("PIOCBIS");
1468 return -1;
1469 }
1470#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 if (!attaching) {
1472#ifdef MIPS
1473 /*
1474 * The SGI PRSABORT doesn't work for pause() so
1475 * we send it a caught signal to wake it up.
1476 */
1477 kill(tcp->pid, SIGINT);
1478#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001479#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001481 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001482 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 perror("PIOCRUN");
1484 return -1;
1485 }
Roland McGrath553a6092002-12-16 20:40:39 +00001486#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001487#endif /* !MIPS*/
1488#ifdef FREEBSD
1489 /* wake up the child if it received the SIGSTOP */
1490 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001491#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 for (;;) {
1493 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001494 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 perror("PIOCWSTOP");
1496 return -1;
1497 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001498 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001499 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001500 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001501 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 break;
1503 }
1504 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001505#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001506 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001507 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1508#else
1509 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1510#endif
1511 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512 perror("PIOCRUN");
1513 return -1;
1514 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001515#ifdef FREEBSD
1516 /* handle the case where we "opened" the child before
1517 it did the kill -STOP */
1518 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1519 tcp->status.PR_WHAT == SIGSTOP)
1520 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001521#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 }
1523 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001524#ifdef FREEBSD
1525 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001526 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001527 /* We are attaching to an already running process.
1528 * Try to figure out the state of the process in syscalls,
1529 * to handle the first event well.
1530 * This is done by having a look at the "wchan" property of the
1531 * process, which tells where it is stopped (if it is). */
1532 FILE * status;
1533 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001534
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001535 sprintf(proc, "/proc/%d/status", tcp->pid);
1536 status = fopen(proc, "r");
1537 if (status &&
1538 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1539 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1540 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1541 strcmp(wchan, "stopevent")) {
1542 /* The process is asleep in the middle of a syscall.
1543 Fake the syscall entry event */
1544 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1545 tcp->status.PR_WHY = PR_SYSENTRY;
1546 trace_syscall(tcp);
1547 }
1548 if (status)
1549 fclose(status);
1550 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001551 }
1552#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001553#ifndef HAVE_POLLABLE_PROCFS
1554 if (proc_poll_pipe[0] != -1)
1555 proc_poller(tcp->pfd);
1556 else if (nprocs > 1) {
1557 proc_poll_open();
1558 proc_poller(last_pfd);
1559 proc_poller(tcp->pfd);
1560 }
1561 last_pfd = tcp->pfd;
1562#endif /* !HAVE_POLLABLE_PROCFS */
1563 return 0;
1564}
1565
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001566#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001567
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001568struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001569pid2tcb(int pid)
1570{
1571 int i;
1572
1573 if (pid <= 0)
1574 return NULL;
1575
1576 for (i = 0; i < tcbtabsize; i++) {
1577 struct tcb *tcp = tcbtab[i];
1578 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1579 return tcp;
1580 }
1581
1582 return NULL;
1583}
1584
1585#ifdef USE_PROCFS
1586
1587static struct tcb *
1588first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589{
1590 int i;
1591 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001592 for (i = 0; i < tcbtabsize; i++) {
1593 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 if (tcp->flags & TCB_INUSE)
1595 return tcp;
1596 }
1597 return NULL;
1598}
1599
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001601pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602{
1603 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604
Roland McGrathca16be82003-01-10 19:55:28 +00001605 for (i = 0; i < tcbtabsize; i++) {
1606 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 if (tcp->pfd != pfd)
1608 continue;
1609 if (tcp->flags & TCB_INUSE)
1610 return tcp;
1611 }
1612 return NULL;
1613}
1614
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001615#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
1617void
Denys Vlasenko12014262011-05-30 14:00:14 +02001618droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619{
1620 if (tcp->pid == 0)
1621 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001622
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001624 if (debug)
1625 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001626
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001627#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628 if (tcp->pfd != -1) {
1629 close(tcp->pfd);
1630 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001631# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001632 if (tcp->pfd_reg != -1) {
1633 close(tcp->pfd_reg);
1634 tcp->pfd_reg = -1;
1635 }
1636 if (tcp->pfd_status != -1) {
1637 close(tcp->pfd_status);
1638 tcp->pfd_status = -1;
1639 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001640# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001641 tcp->flags = 0; /* rebuild_pollv needs it */
1642 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001644#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001645
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001646 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001648
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001649 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650}
1651
Roland McGrath0a463882007-07-05 18:43:16 +00001652/* detach traced process; continue with sig
1653 Never call DETACH twice on the same process as both unattached and
1654 attached-unstopped processes give the same ESRCH. For unattached process we
1655 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656
1657static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001658detach(struct tcb *tcp, int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659{
1660 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001661#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001662 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001663#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664
1665 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001666 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667
1668#ifdef LINUX
1669 /*
1670 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001671 * before detaching. Arghh. We go through hoops
1672 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001674#if defined(SPARC)
1675#undef PTRACE_DETACH
1676#define PTRACE_DETACH PTRACE_SUNDETACH
1677#endif
Roland McGrath02203312007-06-11 22:06:31 +00001678 /*
1679 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
1680 * expected SIGSTOP. We must catch exactly one as otherwise the
1681 * detached process would be left stopped (process state T).
1682 */
1683 catch_sigstop = (tcp->flags & TCB_STARTUP);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001684 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
1685 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001687 }
1688 else if (errno != ESRCH) {
1689 /* Shouldn't happen. */
1690 perror("detach: ptrace(PTRACE_DETACH, ...)");
1691 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001692 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001693 if (errno != ESRCH)
1694 perror("detach: checking sanity");
1695 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001696 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001697 if (errno != ESRCH)
1698 perror("detach: stopping child");
1699 }
Roland McGrath02203312007-06-11 22:06:31 +00001700 else
1701 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001702 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001704#ifdef __WALL
1705 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1706 if (errno == ECHILD) /* Already gone. */
1707 break;
1708 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001709 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001710 break;
1711 }
1712#endif /* __WALL */
1713 /* No __WALL here. */
1714 if (waitpid(tcp->pid, &status, 0) < 0) {
1715 if (errno != ECHILD) {
1716 perror("detach: waiting");
1717 break;
1718 }
1719#ifdef __WCLONE
1720 /* If no processes, try clones. */
1721 if (wait4(tcp->pid, &status, __WCLONE,
1722 NULL) < 0) {
1723 if (errno != ECHILD)
1724 perror("detach: waiting");
1725 break;
1726 }
1727#endif /* __WCLONE */
1728 }
1729#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001730 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001731#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 if (!WIFSTOPPED(status)) {
1733 /* Au revoir, mon ami. */
1734 break;
1735 }
1736 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001737 ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001738 break;
1739 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001740 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001741 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001742 : WSTOPSIG(status));
1743 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001746 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001747#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748
1749#if defined(SUNOS4)
1750 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1751 if (sig && kill(tcp->pid, sig) < 0)
1752 perror("detach: kill");
1753 sig = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001754 error = ptrace_restart(PTRACE_DETACH, tcp, sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755#endif /* SUNOS4 */
1756
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757 if (!qflag)
1758 fprintf(stderr, "Process %u detached\n", tcp->pid);
1759
1760 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001761
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 return error;
1763}
1764
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001765#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001767static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768{
1769 int pid;
1770 int status;
1771
1772 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 }
1774}
1775
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001776#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777
1778static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001779cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780{
1781 int i;
1782 struct tcb *tcp;
1783
Roland McGrathee9d4352002-12-18 04:16:10 +00001784 for (i = 0; i < tcbtabsize; i++) {
1785 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786 if (!(tcp->flags & TCB_INUSE))
1787 continue;
1788 if (debug)
1789 fprintf(stderr,
1790 "cleanup: looking at pid %u\n", tcp->pid);
1791 if (tcp_last &&
1792 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001793 tprintf(" <unfinished ...>");
1794 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 }
1796 if (tcp->flags & TCB_ATTACHED)
1797 detach(tcp, 0);
1798 else {
1799 kill(tcp->pid, SIGCONT);
1800 kill(tcp->pid, SIGTERM);
1801 }
1802 }
1803 if (cflag)
1804 call_summary(outf);
1805}
1806
1807static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001808interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809{
1810 interrupted = 1;
1811}
1812
1813#ifndef HAVE_STRERROR
1814
Roland McGrath6d2b3492002-12-30 00:51:30 +00001815#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001816extern int sys_nerr;
1817extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001818#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819
1820const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001821strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822{
1823 static char buf[64];
1824
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001825 if (err_no < 1 || err_no >= sys_nerr) {
1826 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001827 return buf;
1828 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001829 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830}
1831
1832#endif /* HAVE_STERRROR */
1833
1834#ifndef HAVE_STRSIGNAL
1835
Roland McGrath8f474e02003-01-14 07:53:33 +00001836#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001837extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001839#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1840extern char *_sys_siglist[];
1841#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001842
1843const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001844strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845{
1846 static char buf[64];
1847
1848 if (sig < 1 || sig >= NSIG) {
1849 sprintf(buf, "Unknown signal %d", sig);
1850 return buf;
1851 }
1852#ifdef HAVE__SYS_SIGLIST
1853 return _sys_siglist[sig];
1854#else
1855 return sys_siglist[sig];
1856#endif
1857}
1858
1859#endif /* HAVE_STRSIGNAL */
1860
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001861#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001862
1863static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001864rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865{
1866 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001867
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001868 free(pollv);
1869 pollv = malloc(nprocs * sizeof(pollv[0]));
Roland McGrathee9d4352002-12-18 04:16:10 +00001870 if (pollv == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001871 error_msg_and_die("Out of memory");
Roland McGrathee9d4352002-12-18 04:16:10 +00001872 }
1873
Roland McGrathca16be82003-01-10 19:55:28 +00001874 for (i = j = 0; i < tcbtabsize; i++) {
1875 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876 if (!(tcp->flags & TCB_INUSE))
1877 continue;
1878 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001879 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880 j++;
1881 }
1882 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001883 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884 }
1885}
1886
1887#ifndef HAVE_POLLABLE_PROCFS
1888
1889static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001890proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001892 int i;
1893
1894 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001895 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 }
1897 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001898 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899 }
1900}
1901
1902static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001903proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904{
1905 int i;
1906 int n;
1907 struct proc_pollfd pollinfo;
1908
Denys Vlasenko5d645812011-08-20 12:48:18 +02001909 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1910 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 return n;
1912 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001913 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 }
1915 for (i = 0; i < nprocs; i++) {
1916 if (pollv[i].fd == pollinfo.fd)
1917 pollv[i].revents = pollinfo.revents;
1918 else
1919 pollv[i].revents = 0;
1920 }
1921 poller_pid = pollinfo.pid;
1922 return 1;
1923}
1924
1925static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001926wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927{
1928}
1929
1930static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001931proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932{
1933 struct proc_pollfd pollinfo;
1934 struct sigaction sa;
1935 sigset_t blocked_set, empty_set;
1936 int i;
1937 int n;
1938 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001939#ifdef FREEBSD
1940 struct procfs_status pfs;
1941#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001942
1943 switch (fork()) {
1944 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001945 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 case 0:
1947 break;
1948 default:
1949 return;
1950 }
1951
1952 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1953 sa.sa_flags = 0;
1954 sigemptyset(&sa.sa_mask);
1955 sigaction(SIGHUP, &sa, NULL);
1956 sigaction(SIGINT, &sa, NULL);
1957 sigaction(SIGQUIT, &sa, NULL);
1958 sigaction(SIGPIPE, &sa, NULL);
1959 sigaction(SIGTERM, &sa, NULL);
1960 sa.sa_handler = wakeup_handler;
1961 sigaction(SIGUSR1, &sa, NULL);
1962 sigemptyset(&blocked_set);
1963 sigaddset(&blocked_set, SIGUSR1);
1964 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1965 sigemptyset(&empty_set);
1966
1967 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001968 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 }
1970 n = rl.rlim_cur;
1971 for (i = 0; i < n; i++) {
1972 if (i != pfd && i != proc_poll_pipe[1])
1973 close(i);
1974 }
1975
1976 pollinfo.fd = pfd;
1977 pollinfo.pid = getpid();
1978 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001979#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001980 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1981#else
1982 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1983#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001984 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985 switch (errno) {
1986 case EINTR:
1987 continue;
1988 case EBADF:
1989 pollinfo.revents = POLLERR;
1990 break;
1991 case ENOENT:
1992 pollinfo.revents = POLLHUP;
1993 break;
1994 default:
1995 perror("proc_poller: PIOCWSTOP");
1996 }
1997 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1998 _exit(0);
1999 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002000 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2002 sigsuspend(&empty_set);
2003 }
2004}
2005
2006#endif /* !HAVE_POLLABLE_PROCFS */
2007
2008static int
2009choose_pfd()
2010{
2011 int i, j;
2012 struct tcb *tcp;
2013
2014 static int last;
2015
2016 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002017 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002018 /*
2019 * The previous process is ready to run again. We'll
2020 * let it do so if it is currently in a syscall. This
2021 * heuristic improves the readability of the trace.
2022 */
2023 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002024 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 return pollv[last].fd;
2026 }
2027
2028 for (i = 0; i < nprocs; i++) {
2029 /* Let competing children run round robin. */
2030 j = (i + last + 1) % nprocs;
2031 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2032 tcp = pfd2tcb(pollv[j].fd);
2033 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002034 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 }
2036 droptcb(tcp);
2037 return -1;
2038 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002039 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 last = j;
2041 return pollv[j].fd;
2042 }
2043 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002044 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045}
2046
2047static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002048trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002050#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002051 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002052#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 struct tcb *tcp;
2054 int pfd;
2055 int what;
2056 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002057 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058
2059 for (;;) {
2060 if (interactive)
2061 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2062
2063 if (nprocs == 0)
2064 break;
2065
2066 switch (nprocs) {
2067 case 1:
2068#ifndef HAVE_POLLABLE_PROCFS
2069 if (proc_poll_pipe[0] == -1) {
2070#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002071 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002072 if (!tcp)
2073 continue;
2074 pfd = tcp->pfd;
2075 if (pfd == -1)
2076 continue;
2077 break;
2078#ifndef HAVE_POLLABLE_PROCFS
2079 }
2080 /* fall through ... */
2081#endif /* !HAVE_POLLABLE_PROCFS */
2082 default:
2083#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002084#ifdef POLL_HACK
2085 /* On some systems (e.g. UnixWare) we get too much ugly
2086 "unfinished..." stuff when multiple proceses are in
2087 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002088
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002089 if (in_syscall) {
2090 struct pollfd pv;
2091 tcp = in_syscall;
2092 in_syscall = NULL;
2093 pv.fd = tcp->pfd;
2094 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002095 what = poll(&pv, 1, 1);
2096 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002097 if (interrupted)
2098 return 0;
2099 continue;
2100 }
2101 else if (what == 1 && pv.revents & POLLWANT) {
2102 goto FOUND;
2103 }
2104 }
2105#endif
2106
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 if (poll(pollv, nprocs, INFTIM) < 0) {
2108 if (interrupted)
2109 return 0;
2110 continue;
2111 }
2112#else /* !HAVE_POLLABLE_PROCFS */
2113 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2114 if (interrupted)
2115 return 0;
2116 continue;
2117 }
2118#endif /* !HAVE_POLLABLE_PROCFS */
2119 pfd = choose_pfd();
2120 if (pfd == -1)
2121 continue;
2122 break;
2123 }
2124
2125 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002126 tcp = pfd2tcb(pfd);
2127 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002128 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 }
John Hughesb6643082002-05-23 11:02:22 +00002130#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002131 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002132#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002133 /* Get the status of the process. */
2134 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002135#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002136 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002137#else /* FREEBSD */
2138 /* Thanks to some scheduling mystery, the first poller
2139 sometimes waits for the already processed end of fork
2140 event. Doing a non blocking poll here solves the problem. */
2141 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002142 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002143 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002144 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002145#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 ioctl_errno = errno;
2147#ifndef HAVE_POLLABLE_PROCFS
2148 if (proc_poll_pipe[0] != -1) {
2149 if (ioctl_result < 0)
2150 kill(poller_pid, SIGKILL);
2151 else
2152 kill(poller_pid, SIGUSR1);
2153 }
2154#endif /* !HAVE_POLLABLE_PROCFS */
2155 }
2156 if (interrupted)
2157 return 0;
2158
2159 if (interactive)
2160 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2161
2162 if (ioctl_result < 0) {
2163 /* Find out what happened if it failed. */
2164 switch (ioctl_errno) {
2165 case EINTR:
2166 case EBADF:
2167 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002168#ifdef FREEBSD
2169 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002170#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002171 case ENOENT:
2172 droptcb(tcp);
2173 continue;
2174 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002175 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 }
2177 }
2178
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002179#ifdef FREEBSD
2180 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2181 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002182 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002183 continue;
2184 }
Roland McGrath553a6092002-12-16 20:40:39 +00002185#endif
2186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002187 /* clear the just started flag */
2188 tcp->flags &= ~TCB_STARTUP;
2189
2190 /* set current output file */
2191 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002192 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193
2194 if (cflag) {
2195 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002196#ifdef FREEBSD
2197 char buf[1024];
2198 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199
Denys Vlasenko5d645812011-08-20 12:48:18 +02002200 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2201 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002202 buf[len] = '\0';
2203 sscanf(buf,
2204 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2205 &stime.tv_sec, &stime.tv_usec);
2206 } else
2207 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002208#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2210 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002211#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2213 tcp->stime = stime;
2214 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002215 what = tcp->status.PR_WHAT;
2216 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002217#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002218 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002219 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2220 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002222 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002223 }
2224 }
2225 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002226#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002228#ifdef POLL_HACK
2229 in_syscall = tcp;
2230#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 case PR_SYSEXIT:
2232 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002233 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002234 }
2235 break;
2236 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002237 if (cflag != CFLAG_ONLY_STATS
2238 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002239 printleader(tcp);
2240 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002241 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002242 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002243#ifdef PR_INFO
2244 if (tcp->status.PR_INFO.si_signo == what) {
2245 printleader(tcp);
2246 tprintf(" siginfo=");
2247 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002248 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002249 }
2250#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251 }
2252 break;
2253 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002254 if (cflag != CFLAGS_ONLY_STATS
2255 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002256 printleader(tcp);
2257 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002258 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002259 }
2260 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002261#ifdef FREEBSD
2262 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002263 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002264#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002266 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267 break;
2268 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002269 /* Remember current print column before continuing. */
2270 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002271 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002272#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002273 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002274#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002275 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002276#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002277 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002278 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002279 }
2280 }
2281 return 0;
2282}
2283
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002284#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002285
Roland McGratheb9e2e82009-06-02 16:49:22 -07002286static int
2287trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288{
2289 int pid;
2290 int wait_errno;
2291 int status;
2292 struct tcb *tcp;
2293#ifdef LINUX
2294 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002295 struct rusage *rup = cflag ? &ru : NULL;
2296# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002297 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002298# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299#endif /* LINUX */
2300
Roland McGratheb9e2e82009-06-02 16:49:22 -07002301 while (nprocs != 0) {
Denys Vlasenko222713a2009-03-17 14:29:59 +00002302 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002303 return 0;
2304 if (interactive)
2305 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002307# ifdef __WALL
2308 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002309 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002310 /* this kernel does not support __WALL */
2311 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002312 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002313 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002314 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002315 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002316 pid = wait4(-1, &status, __WCLONE, rup);
2317 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002318 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002319 }
2320 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002321# else
2322 pid = wait4(-1, &status, 0, rup);
2323# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324#endif /* LINUX */
2325#ifdef SUNOS4
2326 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002327#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002329 if (interactive)
2330 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002331
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002332 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002333 switch (wait_errno) {
2334 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002336 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002337 /*
2338 * We would like to verify this case
2339 * but sometimes a race in Solbourne's
2340 * version of SunOS sometimes reports
2341 * ECHILD before sending us SIGCHILD.
2342 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002343 return 0;
2344 default:
2345 errno = wait_errno;
2346 perror("strace: wait");
2347 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002348 }
2349 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002350 if (pid == popen_pid) {
2351 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002352 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002353 continue;
2354 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002355 if (debug) {
2356 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2357#ifdef LINUX
2358 unsigned ev = (unsigned)status >> 16;
2359 if (ev) {
2360 static const char *const event_names[] = {
2361 [PTRACE_EVENT_CLONE] = "CLONE",
2362 [PTRACE_EVENT_FORK] = "FORK",
2363 [PTRACE_EVENT_VFORK] = "VFORK",
2364 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2365 [PTRACE_EVENT_EXEC] = "EXEC",
2366 [PTRACE_EVENT_EXIT] = "EXIT",
2367 };
2368 const char *e;
2369 if (ev < ARRAY_SIZE(event_names))
2370 e = event_names[ev];
2371 else {
2372 sprintf(buf, "?? (%u)", ev);
2373 e = buf;
2374 }
2375 fprintf(stderr, " PTRACE_EVENT_%s", e);
2376 }
2377#endif
2378 strcpy(buf, "???");
2379 if (WIFSIGNALED(status))
2380#ifdef WCOREDUMP
2381 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2382 WCOREDUMP(status) ? "core," : "",
2383 signame(WTERMSIG(status)));
2384#else
2385 sprintf(buf, "WIFSIGNALED,sig=%s",
2386 signame(WTERMSIG(status)));
2387#endif
2388 if (WIFEXITED(status))
2389 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2390 if (WIFSTOPPED(status))
2391 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002392#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002393 if (WIFCONTINUED(status))
2394 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002395#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002396 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2397 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398
2399 /* Look up `pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002400 tcp = pid2tcb(pid);
2401 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002402#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002403 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002404 /* This is needed to go with the CLONE_PTRACE
2405 changes in process.c/util.c: we might see
2406 the child's initial trap before we see the
2407 parent return from the clone syscall.
2408 Leave the child suspended until the parent
2409 returns from its system call. Only then
2410 will we have the association of parent and
2411 child so that we know how to do clearbpt
2412 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002413 tcp = alloctcb(pid);
Denys Vlasenko833fb132011-08-17 11:30:56 +02002414 tcp->flags |= TCB_ATTACHED;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002415 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002416 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002417 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002418 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002419 else
2420 /* This can happen if a clone call used
2421 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002422#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002423 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002424 if (WIFSTOPPED(status))
2425 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002426 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002427 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002428 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002429 /* set current output file */
2430 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002431 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002432#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002433 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002434 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2435 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002436 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002437#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002438
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002439 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002440 if (pid == strace_child)
2441 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002442 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002443 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2444 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002445#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002446 tprintf("+++ killed by %s %s+++",
2447 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002448 WCOREDUMP(status) ? "(core dumped) " : "");
2449#else
2450 tprintf("+++ killed by %s +++",
2451 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002452#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002453 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454 }
2455 droptcb(tcp);
2456 continue;
2457 }
2458 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002459 if (pid == strace_child)
2460 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002461 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002462 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002463 tprintf(" <unfinished ... exit status %d>\n",
2464 WEXITSTATUS(status));
2465 tcp_last = NULL;
2466 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002467 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2468 printleader(tcp);
2469 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2470 printtrailer();
2471 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 droptcb(tcp);
2473 continue;
2474 }
2475 if (!WIFSTOPPED(status)) {
2476 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2477 droptcb(tcp);
2478 continue;
2479 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002481 if (status >> 16) {
Denys Vlasenko833fb132011-08-17 11:30:56 +02002482 /* Ptrace event (we ignore all of them for now) */
2483 goto tracing;
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002484 }
2485
Roland McGrath02203312007-06-11 22:06:31 +00002486 /*
2487 * Interestingly, the process may stop
2488 * with STOPSIG equal to some other signal
Roland McGratheb9e2e82009-06-02 16:49:22 -07002489 * than SIGSTOP if we happend to attach
Roland McGrath02203312007-06-11 22:06:31 +00002490 * just before the process takes a signal.
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002491 * A no-MMU vforked child won't send up a signal,
2492 * so skip the first (lost) execve notification.
Roland McGrath02203312007-06-11 22:06:31 +00002493 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -04002494 if ((tcp->flags & TCB_STARTUP) &&
2495 (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496 /*
2497 * This flag is there to keep us in sync.
2498 * Next time this process stops it should
2499 * really be entering a system call.
2500 */
2501 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002502 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002503 /*
2504 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002505 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002506 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002507 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
2508 droptcb(tcp);
2509 cleanup();
2510 return -1;
2511 }
2512 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002513#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002514 if (ptrace_setoptions) {
2515 if (debug)
2516 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2517 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2518 if (errno != ESRCH) {
2519 /* Should never happen, really */
2520 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002521 }
2522 }
2523 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002524#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002525 goto tracing;
2526 }
2527
Denys Vlasenko75422762011-05-27 14:36:01 +02002528 if (WSTOPSIG(status) != syscall_trap_sig) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002529 if (WSTOPSIG(status) == SIGSTOP &&
2530 (tcp->flags & TCB_SIGTRAPPED)) {
2531 /*
2532 * Trapped attempt to block SIGTRAP
2533 * Hope we are back in control now.
2534 */
2535 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002536 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537 cleanup();
2538 return -1;
2539 }
2540 continue;
2541 }
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002542 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002543 && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002544 siginfo_t si;
2545#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002546 long pc = 0;
2547 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002548
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002549 upeek(tcp, PT_CR_IPSR, &psr);
2550 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002551
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002552# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002553 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002554# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002555# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002556#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002557# define PC_FORMAT_STR ""
2558# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002559#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002560 printleader(tcp);
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002561 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
2562 tprintf("--- ");
2563 printsiginfo(&si, verbose(tcp));
2564 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002565 strsignal(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002566 PC_FORMAT_ARG);
2567 } else
2568 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
2569 strsignal(WSTOPSIG(status)),
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002570 signame(WSTOPSIG(status))
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002571 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002572 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002573 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002574 if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002575 cleanup();
2576 return -1;
2577 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002578 continue;
2579 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002580
2581 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002582 if (interrupted)
2583 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002584
2585 /* This should be syscall entry or exit.
2586 * (Or it still can be that pesky post-execve SIGTRAP!)
2587 * Handle it.
2588 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002589 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2590 /* ptrace() failed in trace_syscall() with ESRCH.
2591 * Likely a result of process disappearing mid-flight.
2592 * Observed case: exit_group() terminating
2593 * all processes in thread group. In this case, threads
2594 * "disappear" in an unpredictable moment without any
2595 * notification to strace via wait().
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002596 */
2597 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002598 if (tcp_last) {
2599 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002600 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002601 */
2602 tcp_last->flags |= TCB_REPRINT;
2603 tprintf(" <unfinished ...>");
2604 printtrailer();
2605 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002606 detach(tcp, 0);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002607 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002608 ptrace(PTRACE_KILL,
2609 tcp->pid, (char *) 1, SIGTERM);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610 droptcb(tcp);
2611 }
2612 continue;
2613 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002614 tracing:
Andreas Schwabccdff482009-10-27 16:27:13 +01002615 /* Remember current print column before continuing. */
2616 tcp->curcol = curcol;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002617 if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002618 cleanup();
2619 return -1;
2620 }
2621 }
2622 return 0;
2623}
2624
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002625#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002626
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002627void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002628tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629{
2630 va_list args;
2631
Andreas Schwabe5355de2009-10-27 16:56:43 +01002632 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002633 if (outf) {
2634 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002635 if (n < 0) {
2636 if (outf != stderr)
2637 perror(outfname == NULL
2638 ? "<writing to pipe>" : outfname);
2639 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002640 curcol += n;
2641 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002642 va_end(args);
2643 return;
2644}
2645
2646void
Denys Vlasenko12014262011-05-30 14:00:14 +02002647printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002649 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002650 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002651 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenkoe62df002011-06-08 16:15:04 +02002652 tprintf(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002653 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002654 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002655 tprintf("= ? <unavailable>\n");
2656 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002657 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002658 tcp_last->flags |= TCB_REPRINT;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002659 tprintf(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002660 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 }
2662 curcol = 0;
2663 if ((followfork == 1 || pflag_seen > 1) && outfname)
2664 tprintf("%-5d ", tcp->pid);
2665 else if (nprocs > 1 && !outfname)
2666 tprintf("[pid %5u] ", tcp->pid);
2667 if (tflag) {
2668 char str[sizeof("HH:MM:SS")];
2669 struct timeval tv, dtv;
2670 static struct timeval otv;
2671
2672 gettimeofday(&tv, NULL);
2673 if (rflag) {
2674 if (otv.tv_sec == 0)
2675 otv = tv;
2676 tv_sub(&dtv, &tv, &otv);
2677 tprintf("%6ld.%06ld ",
2678 (long) dtv.tv_sec, (long) dtv.tv_usec);
2679 otv = tv;
2680 }
2681 else if (tflag > 2) {
2682 tprintf("%ld.%06ld ",
2683 (long) tv.tv_sec, (long) tv.tv_usec);
2684 }
2685 else {
2686 time_t local = tv.tv_sec;
2687 strftime(str, sizeof(str), "%T", localtime(&local));
2688 if (tflag > 1)
2689 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2690 else
2691 tprintf("%s ", str);
2692 }
2693 }
2694 if (iflag)
2695 printcall(tcp);
2696}
2697
2698void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002699tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002700{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002701 if (curcol < acolumn)
2702 tprintf(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002703}
2704
2705void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002706printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002707{
2708 tprintf("\n");
2709 tcp_last = NULL;
2710}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002711
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002712#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002713
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002714int
2715mp_ioctl(int fd, int cmd, void *arg, int size)
2716{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002717 struct iovec iov[2];
2718 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002719
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002720 iov[0].iov_base = &cmd;
2721 iov[0].iov_len = sizeof cmd;
2722 if (arg) {
2723 ++n;
2724 iov[1].iov_base = arg;
2725 iov[1].iov_len = size;
2726 }
Roland McGrath553a6092002-12-16 20:40:39 +00002727
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002728 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002729}
2730
2731#endif