blob: 84b35c8b0de2ba9a8e24ac260669c52fe7565513 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010048#include <sys/utsname.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;
Denys Vlasenkoaa6ec412012-01-24 11:35:38 +010090static int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
91static int interactive = 1;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000092/*
93 * daemonized_tracer supports -D option.
94 * With this option, strace forks twice.
95 * Unlike normal case, with -D *grandparent* process exec's,
96 * becoming a traced process. Child exits (this prevents traced process
97 * from having children it doesn't expect to have), and grandchild
98 * attaches to grandparent similarly to strace -p PID.
99 * This allows for more transparent interaction in cases
100 * when process and its parent are communicating via signals,
101 * wait() etc. Without -D, strace process gets lodged in between,
102 * disrupting parent<->child link.
103 */
104static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000106/* Sometimes we want to print only succeeding syscalls. */
107int not_failing_only = 0;
108
Grant Edwards8a082772011-04-07 20:25:40 +0000109/* Show path associated with fd arguments */
110int show_fd_path = 0;
111
112/* are we filtering traces based on paths? */
113int tracing_paths = 0;
114
Dmitry V. Levina6809652008-11-10 17:14:58 +0000115static int exit_code = 0;
116static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200117static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700118
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000119static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200120static uid_t run_uid;
121static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200124static int acolumn = DEFAULT_ACOLUMN;
125static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100128struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100129static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200130static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200131static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200132static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100134static char *os_release; /* from uname() */
135
Denys Vlasenko4c196382012-01-04 15:11:09 +0100136static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100137static int trace(void);
138static void cleanup(void);
139static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140static sigset_t empty_set, blocked_set;
141
142#ifdef HAVE_SIG_ATOMIC_T
143static volatile sig_atomic_t interrupted;
144#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146#endif /* !HAVE_SIG_ATOMIC_T */
147
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000148#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149
Andreas Schwabe5355de2009-10-27 16:56:43 +0100150static struct tcb *pfd2tcb(int pfd);
151static void reaper(int sig);
152static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000153static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
155#ifndef HAVE_POLLABLE_PROCFS
156
Andreas Schwabe5355de2009-10-27 16:56:43 +0100157static void proc_poll_open(void);
158static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159
160struct proc_pollfd {
161 int fd;
162 int revents;
163 int pid;
164};
165
166static int poller_pid;
167static int proc_poll_pipe[2] = { -1, -1 };
168
169#endif /* !HAVE_POLLABLE_PROCFS */
170
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000171#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000172#define POLLWANT POLLWRNORM
173#else
174#define POLLWANT POLLPRI
175#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000176#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000177
178static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200179usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180{
181 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000182usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000183 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000184 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200185 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000186 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200188-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000189-f -- follow forks, -ff -- with output into separate files\n\
190-F -- attempt to follow vforks, -h -- print help message\n\
191-i -- print instruction pointer at time of syscall\n\
192-q -- suppress messages about attaching, detaching, etc.\n\
193-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
194-T -- print time spent in each syscall, -V -- print version\n\
195-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
196-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000197-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198-a column -- alignment COLUMN for printing syscall results (default %d)\n\
199-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
200 options: trace, abbrev, verbose, raw, signal, read, or write\n\
201-o file -- send trace output to FILE instead of stderr\n\
202-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
203-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000204-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
206-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
207-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000208-E var=val -- put var=val in the environment for command\n\
209-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000210-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000211" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000212-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000213 */
214, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215 exit(exitval);
216}
217
Denys Vlasenko75422762011-05-27 14:36:01 +0200218static void die(void) __attribute__ ((noreturn));
219static void die(void)
220{
221 if (strace_tracer_pid == getpid()) {
222 cflag = 0;
223 cleanup();
224 }
225 exit(1);
226}
227
228static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200229{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100230 char *msg;
231
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000232 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100233
234 /* We want to print entire message with single fprintf to ensure
235 * message integrity if stderr is shared with other programs.
236 * Thus we use vasprintf + single fprintf.
237 */
238 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100239 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100240 if (err_no)
241 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
242 else
243 fprintf(stderr, "%s: %s\n", progname, msg);
244 free(msg);
245 } else {
246 /* malloc in vasprintf failed, try it without malloc */
247 fprintf(stderr, "%s: ", progname);
248 vfprintf(stderr, fmt, p);
249 if (err_no)
250 fprintf(stderr, ": %s\n", strerror(err_no));
251 else
252 putc('\n', stderr);
253 }
254 /* We don't switch stderr to buffered, thus fprintf(stderr)
255 * always flushes its output and this is not necessary: */
256 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200257}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200258
Denys Vlasenko75422762011-05-27 14:36:01 +0200259void error_msg(const char *fmt, ...)
260{
261 va_list p;
262 va_start(p, fmt);
263 verror_msg(0, fmt, p);
264 va_end(p);
265}
266
267void error_msg_and_die(const char *fmt, ...)
268{
269 va_list p;
270 va_start(p, fmt);
271 verror_msg(0, fmt, p);
272 die();
273}
274
275void perror_msg(const char *fmt, ...)
276{
277 va_list p;
278 va_start(p, fmt);
279 verror_msg(errno, fmt, p);
280 va_end(p);
281}
282
283void perror_msg_and_die(const char *fmt, ...)
284{
285 va_list p;
286 va_start(p, fmt);
287 verror_msg(errno, fmt, p);
288 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200289}
290
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200291void die_out_of_memory(void)
292{
293 static bool recursed = 0;
294 if (recursed)
295 exit(1);
296 recursed = 1;
297 error_msg_and_die("Out of memory");
298}
299
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000300#ifdef SVR4
301#ifdef MIPS
302void
303foobar()
304{
305}
306#endif /* MIPS */
307#endif /* SVR4 */
308
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400309/* Glue for systems without a MMU that cannot provide fork() */
310#ifdef HAVE_FORK
311# define strace_vforked 0
312#else
313# define strace_vforked 1
314# define fork() vfork()
315#endif
316
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200317static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000318set_cloexec_flag(int fd)
319{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200320 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000321
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200322 flags = fcntl(fd, F_GETFD);
323 if (flags < 0) {
324 /* Can happen only if fd is bad.
325 * Should never happen: if it does, we have a bug
326 * in the caller. Therefore we just abort
327 * instead of propagating the error.
328 */
329 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330 }
331
332 newflags = flags | FD_CLOEXEC;
333 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200334 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000335
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200336 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000337}
338
339/*
340 * When strace is setuid executable, we have to swap uids
341 * before and after filesystem and process management operations.
342 */
343static void
344swap_uid(void)
345{
346#ifndef SVR4
347 int euid = geteuid(), uid = getuid();
348
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200349 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200350 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000351 }
352#endif
353}
354
Roland McGrath4bfa6262007-07-05 20:03:16 +0000355#if _LFS64_LARGEFILE
356# define fopen_for_output fopen64
357#else
358# define fopen_for_output fopen
359#endif
360
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000361static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200362strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000363{
364 FILE *fp;
365
366 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200367 fp = fopen_for_output(path, "w");
368 if (!fp)
369 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000370 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200371 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000372 return fp;
373}
374
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200375static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376
377#ifndef _PATH_BSHELL
378# define _PATH_BSHELL "/bin/sh"
379#endif
380
381/*
382 * We cannot use standard popen(3) here because we have to distinguish
383 * popen child process from other processes we trace, and standard popen(3)
384 * does not export its child's pid.
385 */
386static FILE *
387strace_popen(const char *command)
388{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200389 FILE *fp;
390 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000391
392 swap_uid();
393 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200394 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200396 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200398 popen_pid = vfork();
399 if (popen_pid == -1)
400 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000401
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200402 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000403 /* child */
404 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200405 if (fds[0] != 0) {
406 if (dup2(fds[0], 0))
407 perror_msg_and_die("dup2");
408 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000409 }
410 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200411 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000412 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200413
414 /* parent */
415 close(fds[0]);
416 swap_uid();
417 fp = fdopen(fds[1], "w");
418 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200419 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200420 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000421}
422
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200423static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000424newoutf(struct tcb *tcp)
425{
426 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000427 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000428 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200429 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000430 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000431}
432
Roland McGrath02203312007-06-11 22:06:31 +0000433static void
434startup_attach(void)
435{
436 int tcbi;
437 struct tcb *tcp;
438
439 /*
440 * Block user interruptions as we would leave the traced
441 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200442 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200443 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000444 */
445 if (interactive)
446 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
447
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000448 if (daemonized_tracer) {
449 pid_t pid = fork();
450 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200451 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000452 }
453 if (pid) { /* parent */
454 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200455 * Wait for grandchild to attach to straced process
456 * (grandparent). Grandchild SIGKILLs us after it attached.
457 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000458 * it proceeds to exec the straced program.
459 */
460 pause();
461 _exit(0); /* paranoia */
462 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200463 /* grandchild */
464 /* We will be the tracer process. Remember our new pid: */
465 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000466 }
467
Roland McGrath02203312007-06-11 22:06:31 +0000468 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
469 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200470
Denys Vlasenkod116a732011-09-05 14:01:33 +0200471 /* Is this a process we should attach to, but not yet attached? */
472 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
473 continue; /* no */
474
475 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000476 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200477 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000478
479#ifdef USE_PROCFS
480 if (proc_open(tcp, 1) < 0) {
481 fprintf(stderr, "trouble opening proc file\n");
482 droptcb(tcp);
483 continue;
484 }
485#else /* !USE_PROCFS */
486# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000487 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000488 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000489 DIR *dir;
490
491 sprintf(procdir, "/proc/%d/task", tcp->pid);
492 dir = opendir(procdir);
493 if (dir != NULL) {
494 unsigned int ntid = 0, nerr = 0;
495 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200496
Roland McGrath02203312007-06-11 22:06:31 +0000497 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200498 struct tcb *cur_tcp;
499 int tid;
500
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000501 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000502 continue;
503 tid = atoi(de->d_name);
504 if (tid <= 0)
505 continue;
506 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200507 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000508 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200509 if (debug)
510 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200511 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200512 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200513 if (debug)
514 fprintf(stderr, "attach to pid %d succeeded\n", tid);
515 cur_tcp = tcp;
516 if (tid != tcp->pid)
517 cur_tcp = alloctcb(tid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200518 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrath02203312007-06-11 22:06:31 +0000519 }
520 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200521 if (interactive) {
522 sigprocmask(SIG_SETMASK, &empty_set, NULL);
523 if (interrupted)
524 goto ret;
525 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
526 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000527 ntid -= nerr;
528 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000529 perror("attach: ptrace(PTRACE_ATTACH, ...)");
530 droptcb(tcp);
531 continue;
532 }
533 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000534 fprintf(stderr, ntid > 1
535? "Process %u attached with %u threads - interrupt to quit\n"
536: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200537 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000538 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200539 if (!(tcp->flags & TCB_STARTUP)) {
540 /* -p PID, we failed to attach to PID itself
541 * but did attach to some of its sibling threads.
542 * Drop PID's tcp.
543 */
544 droptcb(tcp);
545 }
Roland McGrath02203312007-06-11 22:06:31 +0000546 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000547 } /* if (opendir worked) */
548 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200549# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000550 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
551 perror("attach: ptrace(PTRACE_ATTACH, ...)");
552 droptcb(tcp);
553 continue;
554 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200555 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200556 if (debug)
557 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000558
559 if (daemonized_tracer) {
560 /*
561 * It is our grandparent we trace, not a -p PID.
562 * Don't want to just detach on exit, so...
563 */
564 tcp->flags &= ~TCB_ATTACHED;
565 /*
566 * Make parent go away.
567 * Also makes grandparent's wait() unblock.
568 */
569 kill(getppid(), SIGKILL);
570 }
571
Roland McGrath02203312007-06-11 22:06:31 +0000572#endif /* !USE_PROCFS */
573 if (!qflag)
574 fprintf(stderr,
575 "Process %u attached - interrupt to quit\n",
576 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200577 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000578
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200579 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000580 if (interactive)
581 sigprocmask(SIG_SETMASK, &empty_set, NULL);
582}
583
584static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200585startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000586{
587 struct stat statbuf;
588 const char *filename;
589 char pathname[MAXPATHLEN];
590 int pid = 0;
591 struct tcb *tcp;
592
593 filename = argv[0];
594 if (strchr(filename, '/')) {
595 if (strlen(filename) > sizeof pathname - 1) {
596 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200597 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000598 }
599 strcpy(pathname, filename);
600 }
601#ifdef USE_DEBUGGING_EXEC
602 /*
603 * Debuggers customarily check the current directory
604 * first regardless of the path but doing that gives
605 * security geeks a panic attack.
606 */
607 else if (stat(filename, &statbuf) == 0)
608 strcpy(pathname, filename);
609#endif /* USE_DEBUGGING_EXEC */
610 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000611 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000612 int m, n, len;
613
614 for (path = getenv("PATH"); path && *path; path += m) {
615 if (strchr(path, ':')) {
616 n = strchr(path, ':') - path;
617 m = n + 1;
618 }
619 else
620 m = n = strlen(path);
621 if (n == 0) {
622 if (!getcwd(pathname, MAXPATHLEN))
623 continue;
624 len = strlen(pathname);
625 }
626 else if (n > sizeof pathname - 1)
627 continue;
628 else {
629 strncpy(pathname, path, n);
630 len = n;
631 }
632 if (len && pathname[len - 1] != '/')
633 pathname[len++] = '/';
634 strcpy(pathname + len, filename);
635 if (stat(pathname, &statbuf) == 0 &&
636 /* Accept only regular files
637 with some execute bits set.
638 XXX not perfect, might still fail */
639 S_ISREG(statbuf.st_mode) &&
640 (statbuf.st_mode & 0111))
641 break;
642 }
643 }
644 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200645 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000646 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000647 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000648 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200649 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000650 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200651 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
652 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000653 ) {
654 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200655 if (outf != stderr)
656 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000657#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200658# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000659 /* Kludge for SGI, see proc_open for details. */
660 sa.sa_handler = foobar;
661 sa.sa_flags = 0;
662 sigemptyset(&sa.sa_mask);
663 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200664# endif
665# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000666 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200667# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200668 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200669# endif
Roland McGrath02203312007-06-11 22:06:31 +0000670#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000671 if (!daemonized_tracer) {
672 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200673 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674 }
675 if (debug)
676 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000677 }
Roland McGrath02203312007-06-11 22:06:31 +0000678
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200679 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000680 uid_t run_euid = run_uid;
681 gid_t run_egid = run_gid;
682
683 if (statbuf.st_mode & S_ISUID)
684 run_euid = statbuf.st_uid;
685 if (statbuf.st_mode & S_ISGID)
686 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000687 /*
688 * It is important to set groups before we
689 * lose privileges on setuid.
690 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200691 if (initgroups(username, run_gid) < 0) {
692 perror_msg_and_die("initgroups");
693 }
694 if (setregid(run_gid, run_egid) < 0) {
695 perror_msg_and_die("setregid");
696 }
697 if (setreuid(run_uid, run_euid) < 0) {
698 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000699 }
700 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200701 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000702 setreuid(run_uid, run_uid);
703
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000704 if (!daemonized_tracer) {
705 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200706 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000707 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200708 * the immediately following execve syscall.
709 * Can't do this on NOMMU systems, we are after
710 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000711 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400712 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200713 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000714 } else {
715 struct sigaction sv_sigchld;
716 sigaction(SIGCHLD, NULL, &sv_sigchld);
717 /*
718 * Make sure it is not SIG_IGN, otherwise wait
719 * will not block.
720 */
721 signal(SIGCHLD, SIG_DFL);
722 /*
723 * Wait for grandchild to attach to us.
724 * It kills child after that, and wait() unblocks.
725 */
726 alarm(3);
727 wait(NULL);
728 alarm(0);
729 sigaction(SIGCHLD, &sv_sigchld, NULL);
730 }
Roland McGrath02203312007-06-11 22:06:31 +0000731#endif /* !USE_PROCFS */
732
733 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200734 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000735 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000736
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200737 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200738
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200739 if (!daemonized_tracer) {
740 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200741 if (!strace_vforked)
742 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
743 else
744 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200745 }
746 else {
747 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
748 strace_tracer_pid = getpid();
749 /* The tracee is our parent: */
750 pid = getppid();
751 tcp = alloctcb(pid);
752 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000753 tcp->flags |= TCB_ATTACHED;
754 }
Roland McGrath02203312007-06-11 22:06:31 +0000755#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000756 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200757 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000758 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200759#endif
Roland McGrath02203312007-06-11 22:06:31 +0000760}
761
Wang Chaob13c0de2010-11-12 17:25:19 +0800762#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000763static void kill_save_errno(pid_t pid, int sig)
764{
765 int saved_errno = errno;
766
767 (void) kill(pid, sig);
768 errno = saved_errno;
769}
770
Wang Chaob13c0de2010-11-12 17:25:19 +0800771/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000772 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800773 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000774 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800775 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000776static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200777test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800778{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000779 int pid, expected_grandchild = 0, found_grandchild = 0;
780 const unsigned int test_options = PTRACE_O_TRACECLONE |
781 PTRACE_O_TRACEFORK |
782 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800783
Denys Vlasenko5d645812011-08-20 12:48:18 +0200784 pid = fork();
785 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000786 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200787 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000788 pid = getpid();
789 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
790 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
791 __func__);
792 kill(pid, SIGSTOP);
793 if (fork() < 0)
794 perror_msg_and_die("fork");
795 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800796 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000797
798 while (1) {
799 int status, tracee_pid;
800
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000801 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000802 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000803 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000804 if (errno == EINTR)
805 continue;
806 else if (errno == ECHILD)
807 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000808 kill_save_errno(pid, SIGKILL);
809 perror_msg_and_die("%s: unexpected wait result %d",
810 __func__, tracee_pid);
811 }
812 if (WIFEXITED(status)) {
813 if (WEXITSTATUS(status)) {
814 if (tracee_pid != pid)
815 kill_save_errno(pid, SIGKILL);
816 error_msg_and_die("%s: unexpected exit status %u",
817 __func__, WEXITSTATUS(status));
818 }
819 continue;
820 }
821 if (WIFSIGNALED(status)) {
822 if (tracee_pid != pid)
823 kill_save_errno(pid, SIGKILL);
824 error_msg_and_die("%s: unexpected signal %u",
825 __func__, WTERMSIG(status));
826 }
827 if (!WIFSTOPPED(status)) {
828 if (tracee_pid != pid)
829 kill_save_errno(tracee_pid, SIGKILL);
830 kill(pid, SIGKILL);
831 error_msg_and_die("%s: unexpected wait status %x",
832 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000833 }
834 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000835 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000836 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
837 kill_save_errno(tracee_pid, SIGKILL);
838 kill_save_errno(pid, SIGKILL);
839 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800840 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000841 continue;
842 }
843 switch (WSTOPSIG(status)) {
844 case SIGSTOP:
845 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
846 && errno != EINVAL && errno != EIO)
847 perror_msg("PTRACE_SETOPTIONS");
848 break;
849 case SIGTRAP:
850 if (status >> 16 == PTRACE_EVENT_FORK) {
851 long msg = 0;
852
853 if (ptrace(PTRACE_GETEVENTMSG, pid,
854 NULL, (long) &msg) == 0)
855 expected_grandchild = msg;
856 }
857 break;
858 }
859 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
860 kill_save_errno(pid, SIGKILL);
861 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800862 }
863 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000864 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200865 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000866 if (debug)
867 fprintf(stderr, "ptrace_setoptions = %#x\n",
868 ptrace_setoptions);
869 return;
870 }
871 error_msg("Test for PTRACE_O_TRACECLONE failed, "
872 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800873}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200874
875/*
876 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
877 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
878 * and then see whether it will stop with (SIGTRAP | 0x80).
879 *
880 * Use of this option enables correct handling of user-generated SIGTRAPs,
881 * and SIGTRAPs generated by special instructions such as int3 on x86:
882 * _start: .globl _start
883 * int3
884 * movl $42, %ebx
885 * movl $1, %eax
886 * int $0x80
887 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
888 */
889static void
890test_ptrace_setoptions_for_all(void)
891{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000892 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
893 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200894 int pid;
895 int it_worked = 0;
896
897 pid = fork();
898 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200899 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200900
901 if (pid == 0) {
902 pid = getpid();
903 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200904 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000905 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
906 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200907 kill(pid, SIGSTOP);
908 _exit(0); /* parent should see entry into this syscall */
909 }
910
911 while (1) {
912 int status, tracee_pid;
913
914 errno = 0;
915 tracee_pid = wait(&status);
916 if (tracee_pid <= 0) {
917 if (errno == EINTR)
918 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000919 kill_save_errno(pid, SIGKILL);
920 perror_msg_and_die("%s: unexpected wait result %d",
921 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200922 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200923 if (WIFEXITED(status)) {
924 if (WEXITSTATUS(status) == 0)
925 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000926 error_msg_and_die("%s: unexpected exit status %u",
927 __func__, WEXITSTATUS(status));
928 }
929 if (WIFSIGNALED(status)) {
930 error_msg_and_die("%s: unexpected signal %u",
931 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200932 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200933 if (!WIFSTOPPED(status)) {
934 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000935 error_msg_and_die("%s: unexpected wait status %x",
936 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200937 }
938 if (WSTOPSIG(status) == SIGSTOP) {
939 /*
940 * We don't check "options aren't accepted" error.
941 * If it happens, we'll never get (SIGTRAP | 0x80),
942 * and thus will decide to not use the option.
943 * IOW: the outcome of the test will be correct.
944 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000945 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
946 && errno != EINVAL && errno != EIO)
947 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200948 }
949 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
950 it_worked = 1;
951 }
952 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000953 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200954 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200955 }
956 }
957
958 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200959 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200960 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200961 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200962 fprintf(stderr, "ptrace_setoptions = %#x\n",
963 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200964 return;
965 }
966
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000967 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
968 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200969}
Wang Chaob13c0de2010-11-12 17:25:19 +0800970#endif
971
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100972/* Noinline: don't want main to have struct utsname permanently on stack */
973static void __attribute__ ((noinline))
974get_os_release(void)
975{
976 struct utsname u;
977 if (uname(&u) < 0)
978 perror_msg_and_die("uname");
979 os_release = strdup(u.release);
980 if (!os_release)
981 die_out_of_memory();
982}
983
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000985main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 struct tcb *tcp;
988 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000989 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 struct sigaction sa;
991
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000992 progname = argv[0] ? argv[0] : "strace";
993
Denys Vlasenko75422762011-05-27 14:36:01 +0200994 strace_tracer_pid = getpid();
995
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100996 get_os_release();
997
Roland McGrathee9d4352002-12-18 04:16:10 +0000998 /* Allocate the initial tcbtab. */
999 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001000 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001001 if (!tcbtab)
1002 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001003 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001004 if (!tcp)
1005 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001006 for (c = 0; c < tcbtabsize; c++)
1007 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001008
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001010 set_sortby(DEFAULT_SORTBY);
1011 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 qualify("trace=all");
1013 qualify("abbrev=all");
1014 qualify("verbose=all");
1015 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001017 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001018#ifndef USE_PROCFS
1019 "D"
1020#endif
Grant Edwards8a082772011-04-07 20:25:40 +00001021 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 switch (c) {
1023 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001024 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001025 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001026 }
1027 cflag = CFLAG_ONLY_STATS;
1028 break;
1029 case 'C':
1030 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001031 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001032 }
1033 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 break;
1035 case 'd':
1036 debug++;
1037 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001038#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001039 case 'D':
1040 daemonized_tracer = 1;
1041 break;
1042#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001043 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001044 optF = 1;
1045 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 case 'f':
1047 followfork++;
1048 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 case 'h':
1050 usage(stdout, 0);
1051 break;
1052 case 'i':
1053 iflag++;
1054 break;
1055 case 'q':
1056 qflag++;
1057 break;
1058 case 'r':
1059 rflag++;
1060 tflag++;
1061 break;
1062 case 't':
1063 tflag++;
1064 break;
1065 case 'T':
1066 dtime++;
1067 break;
1068 case 'x':
1069 xflag++;
1070 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001071 case 'y':
1072 show_fd_path = 1;
1073 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 case 'v':
1075 qualify("abbrev=none");
1076 break;
1077 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001078 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 exit(0);
1080 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001081 case 'z':
1082 not_failing_only = 1;
1083 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 case 'a':
1085 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001086 if (acolumn < 0)
1087 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 break;
1089 case 'e':
1090 qualify(optarg);
1091 break;
1092 case 'o':
1093 outfname = strdup(optarg);
1094 break;
1095 case 'O':
1096 set_overhead(atoi(optarg));
1097 break;
1098 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001099 pid = atoi(optarg);
1100 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001101 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102 break;
1103 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001104 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001105 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 break;
1107 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001108 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109 tcp->flags |= TCB_ATTACHED;
1110 pflag_seen++;
1111 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001112 case 'P':
1113 tracing_paths = 1;
1114 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001115 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001116 }
1117 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 case 's':
1119 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001120 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001121 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001122 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 break;
1124 case 'S':
1125 set_sortby(optarg);
1126 break;
1127 case 'u':
1128 username = strdup(optarg);
1129 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001130 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001131 if (putenv(optarg) < 0)
1132 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001133 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 default:
1135 usage(stderr, 1);
1136 break;
1137 }
1138 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001139 argv += optind;
1140 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141
Denys Vlasenko102ec492011-08-25 01:27:59 +02001142 acolumn_spaces = malloc(acolumn + 1);
1143 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001144 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001145 memset(acolumn_spaces, ' ', acolumn);
1146 acolumn_spaces[acolumn] = '\0';
1147
Denys Vlasenko837399a2012-01-24 11:37:03 +01001148 /* Must have PROG [ARGS], or -p PID. Not both. */
1149 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001150 usage(stderr, 1);
1151
Wang Chaod322a4b2010-08-05 14:30:11 +08001152 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001153 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001154 }
1155
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001156 if (!followfork)
1157 followfork = optF;
1158
Roland McGrathcb9def62006-04-25 07:48:03 +00001159 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001160 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001161 }
1162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 /* See if they want to run as another user. */
1164 if (username != NULL) {
1165 struct passwd *pent;
1166
1167 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001168 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001170 pent = getpwnam(username);
1171 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001172 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 }
1174 run_uid = pent->pw_uid;
1175 run_gid = pent->pw_gid;
1176 }
1177 else {
1178 run_uid = getuid();
1179 run_gid = getgid();
1180 }
1181
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001182#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001183 if (followfork)
1184 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001185 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001186#endif
1187
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 /* Check if they want to redirect the output. */
1189 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001190 /* See if they want to pipe the output. */
1191 if (outfname[0] == '|' || outfname[0] == '!') {
1192 /*
1193 * We can't do the <outfname>.PID funny business
1194 * when using popen, so prohibit it.
1195 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001196 if (followfork > 1)
1197 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1198 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001199 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001200 else if (followfork <= 1)
1201 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 }
1203
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001204 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001205 char *buf = malloc(BUFSIZ);
1206 if (!buf)
1207 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001209 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001210 if (outfname && argv[0]) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001213 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001214
Roland McGrath54cc1c82007-11-03 23:34:11 +00001215 /* Valid states here:
Denys Vlasenko837399a2012-01-24 11:37:03 +01001216 argv[0] pflag_seen outfname interactive
1217 yes 0 0 1
1218 no 1 0 1
1219 yes 0 1 0
1220 no 1 1 1
Roland McGrath54cc1c82007-11-03 23:34:11 +00001221 */
1222
1223 /* STARTUP_CHILD must be called before the signal handlers get
1224 installed below as they are inherited into the spawned process.
1225 Also we do not need to be protected by them as during interruption
1226 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001227 if (argv[0])
1228 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230 sigemptyset(&empty_set);
1231 sigemptyset(&blocked_set);
1232 sa.sa_handler = SIG_IGN;
1233 sigemptyset(&sa.sa_mask);
1234 sa.sa_flags = 0;
1235 sigaction(SIGTTOU, &sa, NULL);
1236 sigaction(SIGTTIN, &sa, NULL);
Denys Vlasenko837399a2012-01-24 11:37:03 +01001237 /* In interactive mode (if no -o OUTFILE, or -p PID is used),
1238 * fatal signals are blocked across syscall waits, and acted on
1239 * in between. In non-interactive mode, signals are ignored.
1240 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 if (interactive) {
1242 sigaddset(&blocked_set, SIGHUP);
1243 sigaddset(&blocked_set, SIGINT);
1244 sigaddset(&blocked_set, SIGQUIT);
1245 sigaddset(&blocked_set, SIGPIPE);
1246 sigaddset(&blocked_set, SIGTERM);
1247 sa.sa_handler = interrupt;
1248#ifdef SUNOS4
1249 /* POSIX signals on sunos4.1 are a little broken. */
1250 sa.sa_flags = SA_INTERRUPT;
1251#endif /* SUNOS4 */
1252 }
1253 sigaction(SIGHUP, &sa, NULL);
1254 sigaction(SIGINT, &sa, NULL);
1255 sigaction(SIGQUIT, &sa, NULL);
1256 sigaction(SIGPIPE, &sa, NULL);
1257 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001258#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259 sa.sa_handler = reaper;
1260 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001261#else
1262 /* Make sure SIGCHLD has the default action so that waitpid
1263 definitely works without losing track of children. The user
1264 should not have given us a bogus state to inherit, but he might
1265 have. Arguably we should detect SIG_IGN here and pass it on
1266 to children, but probably noone really needs that. */
1267 sa.sa_handler = SIG_DFL;
1268 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001269#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001271 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001272 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001273
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 if (trace() < 0)
1275 exit(1);
1276 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001277 fflush(NULL);
1278 if (exit_code > 0xff) {
1279 /* Child was killed by a signal, mimic that. */
1280 exit_code &= 0xff;
1281 signal(exit_code, SIG_DFL);
1282 raise(exit_code);
1283 /* Paranoia - what if this signal is not fatal?
1284 Exit with 128 + signo then. */
1285 exit_code += 128;
1286 }
1287 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288}
1289
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001290static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001291expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001292{
1293 /* Allocate some more TCBs and expand the table.
1294 We don't want to relocate the TCBs because our
1295 callers have pointers and it would be a pain.
1296 So tcbtab is a table of pointers. Since we never
1297 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001298 int i = tcbtabsize;
1299 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1300 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001301 if (!newtab || !newtcbs)
1302 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001303 tcbtabsize *= 2;
1304 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001305 while (i < tcbtabsize)
1306 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001307}
1308
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001310alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311{
1312 int i;
1313 struct tcb *tcp;
1314
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001315 if (nprocs == tcbtabsize)
1316 expand_tcbtab();
1317
Roland McGrathee9d4352002-12-18 04:16:10 +00001318 for (i = 0; i < tcbtabsize; i++) {
1319 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001321 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001323 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001325#if SUPPORTED_PERSONALITIES > 1
1326 tcp->currpers = current_personality;
1327#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001328#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001330#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001332 if (debug)
1333 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001334 if (command_options_parsed)
1335 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336 return tcp;
1337 }
1338 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001339 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340}
1341
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001342#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001344proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345{
1346 char proc[32];
1347 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001348#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001349 int i;
1350 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351 sigset_t signals;
1352 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001353#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354#ifndef HAVE_POLLABLE_PROCFS
1355 static int last_pfd;
1356#endif
1357
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001358#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001359 /* Open the process pseudo-files in /proc. */
1360 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001361 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1362 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 perror("strace: open(\"/proc/...\", ...)");
1364 return -1;
1365 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001366 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001368 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1369 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001370 perror("strace: open(\"/proc/...\", ...)");
1371 return -1;
1372 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001373 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001374 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001375 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1376 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377 perror("strace: open(\"/proc/...\", ...)");
1378 return -1;
1379 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001380 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001381#else
1382 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001383# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001384 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001385 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001386# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001387 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001388 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001389# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001390 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001391 perror("strace: open(\"/proc/...\", ...)");
1392 return -1;
1393 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001394 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001395#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001396#ifdef FREEBSD
1397 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001398 tcp->pfd_reg = open(proc, O_RDONLY);
1399 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001400 perror("strace: open(\"/proc/.../regs\", ...)");
1401 return -1;
1402 }
1403 if (cflag) {
1404 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001405 tcp->pfd_status = open(proc, O_RDONLY);
1406 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001407 perror("strace: open(\"/proc/.../status\", ...)");
1408 return -1;
1409 }
1410 } else
1411 tcp->pfd_status = -1;
1412#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001413 rebuild_pollv();
1414 if (!attaching) {
1415 /*
1416 * Wait for the child to pause. Because of a race
1417 * condition we have to poll for the event.
1418 */
1419 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001420 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001421 perror("strace: PIOCSTATUS");
1422 return -1;
1423 }
1424 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001425 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001426 }
1427 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001428#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001429 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001430 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001431 perror("strace: PIOCSTOP");
1432 return -1;
1433 }
Roland McGrath553a6092002-12-16 20:40:39 +00001434#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001435#ifdef PIOCSET
1436 /* Set Run-on-Last-Close. */
1437 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001438 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439 perror("PIOCSET PR_RLC");
1440 return -1;
1441 }
1442 /* Set or Reset Inherit-on-Fork. */
1443 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001444 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445 perror("PIOC{SET,RESET} PR_FORK");
1446 return -1;
1447 }
1448#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001449#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1451 perror("PIOCSRLC");
1452 return -1;
1453 }
1454 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1455 perror("PIOC{S,R}FORK");
1456 return -1;
1457 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001458#else /* FREEBSD */
1459 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1460 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1461 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001462 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001463 }
1464 arg &= ~PF_LINGER;
1465 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001466 perror("PIOCSFL");
1467 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001468 }
1469#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001471#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001472 /* Enable all syscall entries we care about. */
1473 premptyset(&syscalls);
1474 for (i = 1; i < MAX_QUALS; ++i) {
1475 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001476 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001477 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001478 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001479 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001480 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001481#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001482 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001483#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001484#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001485 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001486#endif
1487#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001488 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001489#endif
1490#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001491 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001492#endif
1493 }
1494 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 perror("PIOCSENTRY");
1496 return -1;
1497 }
John Hughes19e49982001-10-19 08:59:12 +00001498 /* Enable the syscall exits. */
1499 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500 perror("PIOSEXIT");
1501 return -1;
1502 }
John Hughes19e49982001-10-19 08:59:12 +00001503 /* Enable signals we care about. */
1504 premptyset(&signals);
1505 for (i = 1; i < MAX_QUALS; ++i) {
1506 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001507 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001508 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001509 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 perror("PIOCSTRACE");
1511 return -1;
1512 }
John Hughes19e49982001-10-19 08:59:12 +00001513 /* Enable faults we care about */
1514 premptyset(&faults);
1515 for (i = 1; i < MAX_QUALS; ++i) {
1516 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001517 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001518 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001519 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520 perror("PIOCSFAULT");
1521 return -1;
1522 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001523#else /* FREEBSD */
1524 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001525 arg = S_SIG | S_SCE | S_SCX;
1526 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001527 perror("PIOCBIS");
1528 return -1;
1529 }
1530#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531 if (!attaching) {
1532#ifdef MIPS
1533 /*
1534 * The SGI PRSABORT doesn't work for pause() so
1535 * we send it a caught signal to wake it up.
1536 */
1537 kill(tcp->pid, SIGINT);
1538#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001539#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001541 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001542 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543 perror("PIOCRUN");
1544 return -1;
1545 }
Roland McGrath553a6092002-12-16 20:40:39 +00001546#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001547#endif /* !MIPS*/
1548#ifdef FREEBSD
1549 /* wake up the child if it received the SIGSTOP */
1550 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001551#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 for (;;) {
1553 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001554 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555 perror("PIOCWSTOP");
1556 return -1;
1557 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001558 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001559 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001560 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001561 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 break;
1563 }
1564 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001566 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001567 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1568#else
1569 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1570#endif
1571 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 perror("PIOCRUN");
1573 return -1;
1574 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001575#ifdef FREEBSD
1576 /* handle the case where we "opened" the child before
1577 it did the kill -STOP */
1578 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1579 tcp->status.PR_WHAT == SIGSTOP)
1580 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001581#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 }
1583 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001584#ifdef FREEBSD
1585 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001586 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001587 /* We are attaching to an already running process.
1588 * Try to figure out the state of the process in syscalls,
1589 * to handle the first event well.
1590 * This is done by having a look at the "wchan" property of the
1591 * process, which tells where it is stopped (if it is). */
1592 FILE * status;
1593 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001594
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001595 sprintf(proc, "/proc/%d/status", tcp->pid);
1596 status = fopen(proc, "r");
1597 if (status &&
1598 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1599 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1600 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1601 strcmp(wchan, "stopevent")) {
1602 /* The process is asleep in the middle of a syscall.
1603 Fake the syscall entry event */
1604 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1605 tcp->status.PR_WHY = PR_SYSENTRY;
1606 trace_syscall(tcp);
1607 }
1608 if (status)
1609 fclose(status);
1610 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001611 }
1612#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613#ifndef HAVE_POLLABLE_PROCFS
1614 if (proc_poll_pipe[0] != -1)
1615 proc_poller(tcp->pfd);
1616 else if (nprocs > 1) {
1617 proc_poll_open();
1618 proc_poller(last_pfd);
1619 proc_poller(tcp->pfd);
1620 }
1621 last_pfd = tcp->pfd;
1622#endif /* !HAVE_POLLABLE_PROCFS */
1623 return 0;
1624}
1625
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001626#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001628static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001629pid2tcb(int pid)
1630{
1631 int i;
1632
1633 if (pid <= 0)
1634 return NULL;
1635
1636 for (i = 0; i < tcbtabsize; i++) {
1637 struct tcb *tcp = tcbtab[i];
1638 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1639 return tcp;
1640 }
1641
1642 return NULL;
1643}
1644
1645#ifdef USE_PROCFS
1646
1647static struct tcb *
1648first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649{
1650 int i;
1651 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001652 for (i = 0; i < tcbtabsize; i++) {
1653 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 if (tcp->flags & TCB_INUSE)
1655 return tcp;
1656 }
1657 return NULL;
1658}
1659
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001660static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001661pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662{
1663 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664
Roland McGrathca16be82003-01-10 19:55:28 +00001665 for (i = 0; i < tcbtabsize; i++) {
1666 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667 if (tcp->pfd != pfd)
1668 continue;
1669 if (tcp->flags & TCB_INUSE)
1670 return tcp;
1671 }
1672 return NULL;
1673}
1674
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001675#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676
1677void
Denys Vlasenko12014262011-05-30 14:00:14 +02001678droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679{
1680 if (tcp->pid == 0)
1681 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001682
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001684 if (debug)
1685 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001686
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001687#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688 if (tcp->pfd != -1) {
1689 close(tcp->pfd);
1690 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001691# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001692 if (tcp->pfd_reg != -1) {
1693 close(tcp->pfd_reg);
1694 tcp->pfd_reg = -1;
1695 }
1696 if (tcp->pfd_status != -1) {
1697 close(tcp->pfd_status);
1698 tcp->pfd_status = -1;
1699 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001700# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001701 tcp->flags = 0; /* rebuild_pollv needs it */
1702 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001704#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001705
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001706 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001707 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001708
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001709 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710}
1711
Roland McGrath0a463882007-07-05 18:43:16 +00001712/* detach traced process; continue with sig
1713 Never call DETACH twice on the same process as both unattached and
1714 attached-unstopped processes give the same ESRCH. For unattached process we
1715 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716
1717static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001718detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719{
1720 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001721#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001722 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001723#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724
1725 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001726 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727
1728#ifdef LINUX
1729 /*
1730 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001731 * before detaching. Arghh. We go through hoops
1732 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001734#if defined(SPARC)
1735#undef PTRACE_DETACH
1736#define PTRACE_DETACH PTRACE_SUNDETACH
1737#endif
Roland McGrath02203312007-06-11 22:06:31 +00001738 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001739 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1740 * We must catch exactly one as otherwise the detached process
1741 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001742 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001743 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001744 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001745 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001747 }
1748 else if (errno != ESRCH) {
1749 /* Shouldn't happen. */
1750 perror("detach: ptrace(PTRACE_DETACH, ...)");
1751 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001752 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001753 if (errno != ESRCH)
1754 perror("detach: checking sanity");
1755 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001756 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001757 if (errno != ESRCH)
1758 perror("detach: stopping child");
1759 }
Roland McGrath02203312007-06-11 22:06:31 +00001760 else
1761 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001762 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001764#ifdef __WALL
1765 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1766 if (errno == ECHILD) /* Already gone. */
1767 break;
1768 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001769 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001770 break;
1771 }
1772#endif /* __WALL */
1773 /* No __WALL here. */
1774 if (waitpid(tcp->pid, &status, 0) < 0) {
1775 if (errno != ECHILD) {
1776 perror("detach: waiting");
1777 break;
1778 }
1779#ifdef __WCLONE
1780 /* If no processes, try clones. */
1781 if (wait4(tcp->pid, &status, __WCLONE,
1782 NULL) < 0) {
1783 if (errno != ECHILD)
1784 perror("detach: waiting");
1785 break;
1786 }
1787#endif /* __WCLONE */
1788 }
1789#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001790 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001791#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 if (!WIFSTOPPED(status)) {
1793 /* Au revoir, mon ami. */
1794 break;
1795 }
1796 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001797 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798 break;
1799 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001800 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001801 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001802 : WSTOPSIG(status));
1803 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001806 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001807#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001808
1809#if defined(SUNOS4)
1810 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001811 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812#endif /* SUNOS4 */
1813
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001814 if (!qflag)
1815 fprintf(stderr, "Process %u detached\n", tcp->pid);
1816
1817 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001818
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819 return error;
1820}
1821
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001822#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001823
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001824static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825{
1826 int pid;
1827 int status;
1828
1829 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001830 }
1831}
1832
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001833#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834
1835static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001836cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001837{
1838 int i;
1839 struct tcb *tcp;
1840
Roland McGrathee9d4352002-12-18 04:16:10 +00001841 for (i = 0; i < tcbtabsize; i++) {
1842 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843 if (!(tcp->flags & TCB_INUSE))
1844 continue;
1845 if (debug)
1846 fprintf(stderr,
1847 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001848 if (printing_tcp &&
1849 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1850 tprints(" <unfinished ...>\n");
1851 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001852 }
1853 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001854 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001855 else {
1856 kill(tcp->pid, SIGCONT);
1857 kill(tcp->pid, SIGTERM);
1858 }
1859 }
1860 if (cflag)
1861 call_summary(outf);
1862}
1863
1864static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001865interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001866{
1867 interrupted = 1;
1868}
1869
1870#ifndef HAVE_STRERROR
1871
Roland McGrath6d2b3492002-12-30 00:51:30 +00001872#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001873extern int sys_nerr;
1874extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001875#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001876
1877const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001878strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879{
1880 static char buf[64];
1881
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001882 if (err_no < 1 || err_no >= sys_nerr) {
1883 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001884 return buf;
1885 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001886 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887}
1888
1889#endif /* HAVE_STERRROR */
1890
1891#ifndef HAVE_STRSIGNAL
1892
Roland McGrath8f474e02003-01-14 07:53:33 +00001893#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001894extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001895#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001896#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1897extern char *_sys_siglist[];
1898#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001899
1900const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001901strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902{
1903 static char buf[64];
1904
1905 if (sig < 1 || sig >= NSIG) {
1906 sprintf(buf, "Unknown signal %d", sig);
1907 return buf;
1908 }
1909#ifdef HAVE__SYS_SIGLIST
1910 return _sys_siglist[sig];
1911#else
1912 return sys_siglist[sig];
1913#endif
1914}
1915
1916#endif /* HAVE_STRSIGNAL */
1917
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001918#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919
1920static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001921rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922{
1923 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001925 free(pollv);
1926 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001927 if (!pollv)
1928 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001929
Roland McGrathca16be82003-01-10 19:55:28 +00001930 for (i = j = 0; i < tcbtabsize; i++) {
1931 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932 if (!(tcp->flags & TCB_INUSE))
1933 continue;
1934 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001935 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 j++;
1937 }
1938 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001939 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 }
1941}
1942
1943#ifndef HAVE_POLLABLE_PROCFS
1944
1945static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001946proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948 int i;
1949
1950 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001951 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 }
1953 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001954 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 }
1956}
1957
1958static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001959proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960{
1961 int i;
1962 int n;
1963 struct proc_pollfd pollinfo;
1964
Denys Vlasenko5d645812011-08-20 12:48:18 +02001965 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1966 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001967 return n;
1968 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001969 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001970 }
1971 for (i = 0; i < nprocs; i++) {
1972 if (pollv[i].fd == pollinfo.fd)
1973 pollv[i].revents = pollinfo.revents;
1974 else
1975 pollv[i].revents = 0;
1976 }
1977 poller_pid = pollinfo.pid;
1978 return 1;
1979}
1980
1981static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001982wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001983{
1984}
1985
1986static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001987proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001988{
1989 struct proc_pollfd pollinfo;
1990 struct sigaction sa;
1991 sigset_t blocked_set, empty_set;
1992 int i;
1993 int n;
1994 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001995#ifdef FREEBSD
1996 struct procfs_status pfs;
1997#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998
1999 switch (fork()) {
2000 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002001 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002 case 0:
2003 break;
2004 default:
2005 return;
2006 }
2007
2008 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2009 sa.sa_flags = 0;
2010 sigemptyset(&sa.sa_mask);
2011 sigaction(SIGHUP, &sa, NULL);
2012 sigaction(SIGINT, &sa, NULL);
2013 sigaction(SIGQUIT, &sa, NULL);
2014 sigaction(SIGPIPE, &sa, NULL);
2015 sigaction(SIGTERM, &sa, NULL);
2016 sa.sa_handler = wakeup_handler;
2017 sigaction(SIGUSR1, &sa, NULL);
2018 sigemptyset(&blocked_set);
2019 sigaddset(&blocked_set, SIGUSR1);
2020 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2021 sigemptyset(&empty_set);
2022
2023 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002024 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 }
2026 n = rl.rlim_cur;
2027 for (i = 0; i < n; i++) {
2028 if (i != pfd && i != proc_poll_pipe[1])
2029 close(i);
2030 }
2031
2032 pollinfo.fd = pfd;
2033 pollinfo.pid = getpid();
2034 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002035#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002036 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2037#else
2038 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2039#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002040 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 switch (errno) {
2042 case EINTR:
2043 continue;
2044 case EBADF:
2045 pollinfo.revents = POLLERR;
2046 break;
2047 case ENOENT:
2048 pollinfo.revents = POLLHUP;
2049 break;
2050 default:
2051 perror("proc_poller: PIOCWSTOP");
2052 }
2053 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2054 _exit(0);
2055 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2058 sigsuspend(&empty_set);
2059 }
2060}
2061
2062#endif /* !HAVE_POLLABLE_PROCFS */
2063
2064static int
2065choose_pfd()
2066{
2067 int i, j;
2068 struct tcb *tcp;
2069
2070 static int last;
2071
2072 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002073 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002074 /*
2075 * The previous process is ready to run again. We'll
2076 * let it do so if it is currently in a syscall. This
2077 * heuristic improves the readability of the trace.
2078 */
2079 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002080 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002081 return pollv[last].fd;
2082 }
2083
2084 for (i = 0; i < nprocs; i++) {
2085 /* Let competing children run round robin. */
2086 j = (i + last + 1) % nprocs;
2087 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2088 tcp = pfd2tcb(pollv[j].fd);
2089 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002090 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 }
2092 droptcb(tcp);
2093 return -1;
2094 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002095 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002096 last = j;
2097 return pollv[j].fd;
2098 }
2099 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002100 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101}
2102
2103static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002104trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002105{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002106#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002107 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002108#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109 struct tcb *tcp;
2110 int pfd;
2111 int what;
2112 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002113 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114
2115 for (;;) {
2116 if (interactive)
2117 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2118
2119 if (nprocs == 0)
2120 break;
2121
2122 switch (nprocs) {
2123 case 1:
2124#ifndef HAVE_POLLABLE_PROCFS
2125 if (proc_poll_pipe[0] == -1) {
2126#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002127 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 if (!tcp)
2129 continue;
2130 pfd = tcp->pfd;
2131 if (pfd == -1)
2132 continue;
2133 break;
2134#ifndef HAVE_POLLABLE_PROCFS
2135 }
2136 /* fall through ... */
2137#endif /* !HAVE_POLLABLE_PROCFS */
2138 default:
2139#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002140#ifdef POLL_HACK
2141 /* On some systems (e.g. UnixWare) we get too much ugly
2142 "unfinished..." stuff when multiple proceses are in
2143 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002144
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002145 if (in_syscall) {
2146 struct pollfd pv;
2147 tcp = in_syscall;
2148 in_syscall = NULL;
2149 pv.fd = tcp->pfd;
2150 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002151 what = poll(&pv, 1, 1);
2152 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002153 if (interrupted)
2154 return 0;
2155 continue;
2156 }
2157 else if (what == 1 && pv.revents & POLLWANT) {
2158 goto FOUND;
2159 }
2160 }
2161#endif
2162
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002163 if (poll(pollv, nprocs, INFTIM) < 0) {
2164 if (interrupted)
2165 return 0;
2166 continue;
2167 }
2168#else /* !HAVE_POLLABLE_PROCFS */
2169 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2170 if (interrupted)
2171 return 0;
2172 continue;
2173 }
2174#endif /* !HAVE_POLLABLE_PROCFS */
2175 pfd = choose_pfd();
2176 if (pfd == -1)
2177 continue;
2178 break;
2179 }
2180
2181 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002182 tcp = pfd2tcb(pfd);
2183 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002184 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002185 }
John Hughesb6643082002-05-23 11:02:22 +00002186#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002187 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002188#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 /* Get the status of the process. */
2190 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002191#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002192 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002193#else /* FREEBSD */
2194 /* Thanks to some scheduling mystery, the first poller
2195 sometimes waits for the already processed end of fork
2196 event. Doing a non blocking poll here solves the problem. */
2197 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002198 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002199 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002200 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002201#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002202 ioctl_errno = errno;
2203#ifndef HAVE_POLLABLE_PROCFS
2204 if (proc_poll_pipe[0] != -1) {
2205 if (ioctl_result < 0)
2206 kill(poller_pid, SIGKILL);
2207 else
2208 kill(poller_pid, SIGUSR1);
2209 }
2210#endif /* !HAVE_POLLABLE_PROCFS */
2211 }
2212 if (interrupted)
2213 return 0;
2214
2215 if (interactive)
2216 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2217
2218 if (ioctl_result < 0) {
2219 /* Find out what happened if it failed. */
2220 switch (ioctl_errno) {
2221 case EINTR:
2222 case EBADF:
2223 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002224#ifdef FREEBSD
2225 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002226#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002227 case ENOENT:
2228 droptcb(tcp);
2229 continue;
2230 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002231 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002232 }
2233 }
2234
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002235#ifdef FREEBSD
2236 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2237 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002238 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002239 continue;
2240 }
Roland McGrath553a6092002-12-16 20:40:39 +00002241#endif
2242
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002243 /* clear the just started flag */
2244 tcp->flags &= ~TCB_STARTUP;
2245
2246 /* set current output file */
2247 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002248 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002249
2250 if (cflag) {
2251 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002252#ifdef FREEBSD
2253 char buf[1024];
2254 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002255
Denys Vlasenko5d645812011-08-20 12:48:18 +02002256 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2257 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002258 buf[len] = '\0';
2259 sscanf(buf,
2260 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2261 &stime.tv_sec, &stime.tv_usec);
2262 } else
2263 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002264#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2266 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002267#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002268 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2269 tcp->stime = stime;
2270 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002271 what = tcp->status.PR_WHAT;
2272 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002273#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002274 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002275 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2276 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002277 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002278 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002279 }
2280 }
2281 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002282#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002283 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002284#ifdef POLL_HACK
2285 in_syscall = tcp;
2286#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287 case PR_SYSEXIT:
2288 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002289 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002290 }
2291 break;
2292 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002293 if (cflag != CFLAG_ONLY_STATS
2294 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002295 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002296 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002297 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002298 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002299#ifdef PR_INFO
2300 if (tcp->status.PR_INFO.si_signo == what) {
2301 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002302 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002303 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002304 tprints("\n");
2305 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002306 }
2307#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 }
2309 break;
2310 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002311 if (cflag != CFLAGS_ONLY_STATS
2312 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002313 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002314 tprintf("=== FAULT %d ===\n", what);
2315 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002316 }
2317 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002318#ifdef FREEBSD
2319 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002320 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002321#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002322 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002323 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324 break;
2325 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002326 /* Remember current print column before continuing. */
2327 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002328 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002329#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002330 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002331#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002332 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002333#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002334 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002335 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 }
2337 }
2338 return 0;
2339}
2340
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002341#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002342
Roland McGratheb9e2e82009-06-02 16:49:22 -07002343static int
2344trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002346#ifdef LINUX
2347 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002348 struct rusage *rup = cflag ? &ru : NULL;
2349# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002350 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002351# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352#endif /* LINUX */
2353
Roland McGratheb9e2e82009-06-02 16:49:22 -07002354 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002355 int pid;
2356 int wait_errno;
2357 int status, sig;
2358 struct tcb *tcp;
2359 unsigned event;
2360
Denys Vlasenko222713a2009-03-17 14:29:59 +00002361 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002362 return 0;
2363 if (interactive)
2364 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002365#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002366# ifdef __WALL
2367 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002368 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002369 /* this kernel does not support __WALL */
2370 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002371 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002372 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002373 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002374 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002375 pid = wait4(-1, &status, __WCLONE, rup);
2376 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002377 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002378 }
2379 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002380# else
2381 pid = wait4(-1, &status, 0, rup);
2382# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002383#endif /* LINUX */
2384#ifdef SUNOS4
2385 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002386#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002388 if (interactive)
2389 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002391 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002392 switch (wait_errno) {
2393 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002395 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396 /*
2397 * We would like to verify this case
2398 * but sometimes a race in Solbourne's
2399 * version of SunOS sometimes reports
2400 * ECHILD before sending us SIGCHILD.
2401 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002402 return 0;
2403 default:
2404 errno = wait_errno;
2405 perror("strace: wait");
2406 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407 }
2408 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002409 if (pid == popen_pid) {
2410 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002411 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002412 continue;
2413 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002414
2415 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002416 if (debug) {
2417 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2418#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002419 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002420 static const char *const event_names[] = {
2421 [PTRACE_EVENT_CLONE] = "CLONE",
2422 [PTRACE_EVENT_FORK] = "FORK",
2423 [PTRACE_EVENT_VFORK] = "VFORK",
2424 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2425 [PTRACE_EVENT_EXEC] = "EXEC",
2426 [PTRACE_EVENT_EXIT] = "EXIT",
2427 };
2428 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002429 if (event < ARRAY_SIZE(event_names))
2430 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002431 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002432 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002433 e = buf;
2434 }
2435 fprintf(stderr, " PTRACE_EVENT_%s", e);
2436 }
2437#endif
2438 strcpy(buf, "???");
2439 if (WIFSIGNALED(status))
2440#ifdef WCOREDUMP
2441 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2442 WCOREDUMP(status) ? "core," : "",
2443 signame(WTERMSIG(status)));
2444#else
2445 sprintf(buf, "WIFSIGNALED,sig=%s",
2446 signame(WTERMSIG(status)));
2447#endif
2448 if (WIFEXITED(status))
2449 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2450 if (WIFSTOPPED(status))
2451 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002452#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002453 if (WIFCONTINUED(status))
2454 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002455#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002456 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2457 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002458
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002459 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002460 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002461
2462#ifdef LINUX
2463 /* Under Linux, execve changes pid to thread leader's pid,
2464 * and we see this changed pid on EVENT_EXEC and later,
2465 * execve sysexit. Leader "disappears" without exit
2466 * notification. Let user know that, drop leader's tcb,
2467 * and fix up pid in execve thread's tcb.
2468 * Effectively, execve thread's tcb replaces leader's tcb.
2469 *
2470 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2471 * on exit syscall) in multithreaded programs exactly
2472 * in order to handle this case.
2473 *
2474 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2475 * On 2.6 and earlier, it can return garbage.
2476 */
2477 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2478 long old_pid = 0;
2479 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2480 && old_pid > 0
2481 && old_pid != pid
2482 ) {
2483 struct tcb *execve_thread = pid2tcb(old_pid);
2484 if (tcp) {
2485 outf = tcp->outf;
2486 curcol = tcp->curcol;
2487 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002488 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002489 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002490 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002491 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2492 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002493 fflush(outf);
2494 }
2495 if (execve_thread) {
2496 /* swap output FILEs (needed for -ff) */
2497 tcp->outf = execve_thread->outf;
2498 execve_thread->outf = outf;
2499 }
2500 droptcb(tcp);
2501 }
2502 tcp = execve_thread;
2503 if (tcp) {
2504 tcp->pid = pid;
2505 tcp->flags |= TCB_REPRINT;
2506 }
2507 }
2508 }
2509#endif
2510
Denys Vlasenko5d645812011-08-20 12:48:18 +02002511 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002512#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002513 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002514 /* This is needed to go with the CLONE_PTRACE
2515 changes in process.c/util.c: we might see
2516 the child's initial trap before we see the
2517 parent return from the clone syscall.
2518 Leave the child suspended until the parent
2519 returns from its system call. Only then
2520 will we have the association of parent and
2521 child so that we know how to do clearbpt
2522 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002523 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002524 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002525 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002526 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002527 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002528 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002529 else
2530 /* This can happen if a clone call used
2531 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002532#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002533 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002534 if (WIFSTOPPED(status))
2535 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002536 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002537 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002538 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002539 /* set current output file */
2540 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002541 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002542#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002543 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002544 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2545 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002547#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002548
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002549 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002550 if (pid == strace_child)
2551 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002552 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002553 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2554 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002555#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002556 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002557 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002558 WCOREDUMP(status) ? "(core dumped) " : "");
2559#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002560 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002561 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002562#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002563 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002564 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002565 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 droptcb(tcp);
2567 continue;
2568 }
2569 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002570 if (pid == strace_child)
2571 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002572 if (tcp == printing_tcp) {
2573 tprints(" <unfinished ...>\n");
2574 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002575 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002576 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2577 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002578 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2579 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002580 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002581 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002582 droptcb(tcp);
2583 continue;
2584 }
2585 if (!WIFSTOPPED(status)) {
2586 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2587 droptcb(tcp);
2588 continue;
2589 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002590
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002591 /* Is this the very first time we see this tracee stopped? */
2592 if (tcp->flags & TCB_STARTUP) {
2593 if (debug)
2594 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002595 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002596 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002597 /*
2598 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002599 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002600 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002601 if (clearbpt(tcp) < 0) {
2602 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002603 droptcb(tcp);
2604 cleanup();
2605 return -1;
2606 }
2607 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002608#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002609 if (ptrace_setoptions) {
2610 if (debug)
2611 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2612 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2613 if (errno != ESRCH) {
2614 /* Should never happen, really */
2615 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002616 }
2617 }
2618 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002619#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002620 }
2621
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002622 if (event != 0) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002623 /* Ptrace event (we ignore all of them for now) */
2624 goto restart_tracee_with_sig_0;
2625 }
2626
2627 sig = WSTOPSIG(status);
2628
2629 /* Is this post-attach SIGSTOP?
2630 * Interestingly, the process may stop
2631 * with STOPSIG equal to some other signal
2632 * than SIGSTOP if we happend to attach
2633 * just before the process takes a signal.
2634 */
2635 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2636 if (debug)
2637 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2638 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002639 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002640 }
2641
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002642 if (sig != syscall_trap_sig) {
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002643 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002644 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002645 siginfo_t si;
2646#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002647 long pc = 0;
2648 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002649
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002650 upeek(tcp, PT_CR_IPSR, &psr);
2651 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002652
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002653# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002654 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002655# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002656# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002657#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002658# define PC_FORMAT_STR ""
2659# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002660#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 printleader(tcp);
Dmitry V. Levin436d8922011-11-29 00:15:59 +00002662 if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002663 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002664 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002665 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002666 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002667 PC_FORMAT_ARG);
2668 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002669 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002670 strsignal(sig),
2671 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002672 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002673 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002674 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002675 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002676 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002677 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002678
2679 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002680 if (interrupted)
2681 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002682
2683 /* This should be syscall entry or exit.
2684 * (Or it still can be that pesky post-execve SIGTRAP!)
2685 * Handle it.
2686 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002687 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2688 /* ptrace() failed in trace_syscall() with ESRCH.
2689 * Likely a result of process disappearing mid-flight.
2690 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002691 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002692 */
2693 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002694 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002695 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002696 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002697 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002698 printing_tcp->flags |= TCB_REPRINT;
2699 tprints(" <unfinished ...>\n");
2700 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002701 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002702 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002703 /* We assume that ptrace error was caused by process death.
2704 * We used to detach(tcp) here, but since we no longer
2705 * implement "detach before death" policy/hack,
2706 * we can let this process to report its death to us
2707 * normally, via WIFEXITED or WIFSIGNALED wait status.
2708 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002709 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002710 /* It's our real child (and we also trace it) */
2711 /* my_tkill(pid, SIGKILL); - why? */
2712 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002713 }
2714 continue;
2715 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002716 restart_tracee_with_sig_0:
2717 sig = 0;
2718 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002719 /* Remember current print column before continuing. */
2720 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002721 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002722 cleanup();
2723 return -1;
2724 }
2725 }
2726 return 0;
2727}
2728
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002729#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002730
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002731void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002732tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002733{
2734 va_list args;
2735
Andreas Schwabe5355de2009-10-27 16:56:43 +01002736 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002737 if (outf) {
2738 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002739 if (n < 0) {
2740 if (outf != stderr)
2741 perror(outfname == NULL
2742 ? "<writing to pipe>" : outfname);
2743 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002744 curcol += n;
2745 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002746 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002747}
2748
2749void
2750tprints(const char *str)
2751{
2752 if (outf) {
2753 int n = fputs(str, outf);
2754 if (n >= 0) {
2755 curcol += strlen(str);
2756 return;
2757 }
2758 if (outf != stderr)
2759 perror(outfname == NULL
2760 ? "<writing to pipe>" : outfname);
2761 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002762}
2763
2764void
Denys Vlasenko12014262011-05-30 14:00:14 +02002765printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002766{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002767 if (printing_tcp) {
2768 if (printing_tcp->ptrace_errno) {
2769 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002770 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002771 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002772 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002773 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002774 printing_tcp->ptrace_errno = 0;
2775 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2776 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002777 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002778 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002779 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002780
2781 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002782 curcol = 0;
2783 if ((followfork == 1 || pflag_seen > 1) && outfname)
2784 tprintf("%-5d ", tcp->pid);
2785 else if (nprocs > 1 && !outfname)
2786 tprintf("[pid %5u] ", tcp->pid);
2787 if (tflag) {
2788 char str[sizeof("HH:MM:SS")];
2789 struct timeval tv, dtv;
2790 static struct timeval otv;
2791
2792 gettimeofday(&tv, NULL);
2793 if (rflag) {
2794 if (otv.tv_sec == 0)
2795 otv = tv;
2796 tv_sub(&dtv, &tv, &otv);
2797 tprintf("%6ld.%06ld ",
2798 (long) dtv.tv_sec, (long) dtv.tv_usec);
2799 otv = tv;
2800 }
2801 else if (tflag > 2) {
2802 tprintf("%ld.%06ld ",
2803 (long) tv.tv_sec, (long) tv.tv_usec);
2804 }
2805 else {
2806 time_t local = tv.tv_sec;
2807 strftime(str, sizeof(str), "%T", localtime(&local));
2808 if (tflag > 1)
2809 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2810 else
2811 tprintf("%s ", str);
2812 }
2813 }
2814 if (iflag)
2815 printcall(tcp);
2816}
2817
2818void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002819tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002820{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002821 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002822 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002823}
2824
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002825#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002826
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002827int
2828mp_ioctl(int fd, int cmd, void *arg, int size)
2829{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002830 struct iovec iov[2];
2831 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002832
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002833 iov[0].iov_base = &cmd;
2834 iov[0].iov_len = sizeof cmd;
2835 if (arg) {
2836 ++n;
2837 iov[1].iov_base = arg;
2838 iov[1].iov_len = size;
2839 }
Roland McGrath553a6092002-12-16 20:40:39 +00002840
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002841 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002842}
2843
2844#endif