blob: 7cbcb0cde38d97b299914c4cf8e585c6dc628efb [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;
Andreas Schwabccdff482009-10-27 16:27:13 +0100128static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200129static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200130static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200131static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100133static char *os_release; /* from uname() */
134
Denys Vlasenko4c196382012-01-04 15:11:09 +0100135static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100136static int trace(void);
137static void cleanup(void);
138static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139static sigset_t empty_set, blocked_set;
140
141#ifdef HAVE_SIG_ATOMIC_T
142static volatile sig_atomic_t interrupted;
143#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000145#endif /* !HAVE_SIG_ATOMIC_T */
146
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000147#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
Andreas Schwabe5355de2009-10-27 16:56:43 +0100149static struct tcb *pfd2tcb(int pfd);
150static void reaper(int sig);
151static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000152static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
154#ifndef HAVE_POLLABLE_PROCFS
155
Andreas Schwabe5355de2009-10-27 16:56:43 +0100156static void proc_poll_open(void);
157static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158
159struct proc_pollfd {
160 int fd;
161 int revents;
162 int pid;
163};
164
165static int poller_pid;
166static int proc_poll_pipe[2] = { -1, -1 };
167
168#endif /* !HAVE_POLLABLE_PROCFS */
169
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000170#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000171#define POLLWANT POLLWRNORM
172#else
173#define POLLWANT POLLPRI
174#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000175#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176
177static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200178usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179{
180 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000181usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000182 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000183 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200184 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000185 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200187-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188-f -- follow forks, -ff -- with output into separate files\n\
189-F -- attempt to follow vforks, -h -- print help message\n\
190-i -- print instruction pointer at time of syscall\n\
191-q -- suppress messages about attaching, detaching, etc.\n\
192-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
193-T -- print time spent in each syscall, -V -- print version\n\
194-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
195-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000196-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197-a column -- alignment COLUMN for printing syscall results (default %d)\n\
198-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
199 options: trace, abbrev, verbose, raw, signal, read, or write\n\
200-o file -- send trace output to FILE instead of stderr\n\
201-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
202-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000203-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
205-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
206-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000207-E var=val -- put var=val in the environment for command\n\
208-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000209-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000210" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000211-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000212 */
213, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214 exit(exitval);
215}
216
Denys Vlasenko75422762011-05-27 14:36:01 +0200217static void die(void) __attribute__ ((noreturn));
218static void die(void)
219{
220 if (strace_tracer_pid == getpid()) {
221 cflag = 0;
222 cleanup();
223 }
224 exit(1);
225}
226
227static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200228{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100229 char *msg;
230
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000231 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100232
233 /* We want to print entire message with single fprintf to ensure
234 * message integrity if stderr is shared with other programs.
235 * Thus we use vasprintf + single fprintf.
236 */
237 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100238 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100239 if (err_no)
240 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
241 else
242 fprintf(stderr, "%s: %s\n", progname, msg);
243 free(msg);
244 } else {
245 /* malloc in vasprintf failed, try it without malloc */
246 fprintf(stderr, "%s: ", progname);
247 vfprintf(stderr, fmt, p);
248 if (err_no)
249 fprintf(stderr, ": %s\n", strerror(err_no));
250 else
251 putc('\n', stderr);
252 }
253 /* We don't switch stderr to buffered, thus fprintf(stderr)
254 * always flushes its output and this is not necessary: */
255 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200256}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200257
Denys Vlasenko75422762011-05-27 14:36:01 +0200258void error_msg(const char *fmt, ...)
259{
260 va_list p;
261 va_start(p, fmt);
262 verror_msg(0, fmt, p);
263 va_end(p);
264}
265
266void error_msg_and_die(const char *fmt, ...)
267{
268 va_list p;
269 va_start(p, fmt);
270 verror_msg(0, fmt, p);
271 die();
272}
273
274void perror_msg(const char *fmt, ...)
275{
276 va_list p;
277 va_start(p, fmt);
278 verror_msg(errno, fmt, p);
279 va_end(p);
280}
281
282void perror_msg_and_die(const char *fmt, ...)
283{
284 va_list p;
285 va_start(p, fmt);
286 verror_msg(errno, fmt, p);
287 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200288}
289
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200290void die_out_of_memory(void)
291{
292 static bool recursed = 0;
293 if (recursed)
294 exit(1);
295 recursed = 1;
296 error_msg_and_die("Out of memory");
297}
298
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299#ifdef SVR4
300#ifdef MIPS
301void
302foobar()
303{
304}
305#endif /* MIPS */
306#endif /* SVR4 */
307
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400308/* Glue for systems without a MMU that cannot provide fork() */
309#ifdef HAVE_FORK
310# define strace_vforked 0
311#else
312# define strace_vforked 1
313# define fork() vfork()
314#endif
315
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200316static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000317set_cloexec_flag(int fd)
318{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200319 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000320
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200321 flags = fcntl(fd, F_GETFD);
322 if (flags < 0) {
323 /* Can happen only if fd is bad.
324 * Should never happen: if it does, we have a bug
325 * in the caller. Therefore we just abort
326 * instead of propagating the error.
327 */
328 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000329 }
330
331 newflags = flags | FD_CLOEXEC;
332 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200333 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000334
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200335 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000336}
337
338/*
339 * When strace is setuid executable, we have to swap uids
340 * before and after filesystem and process management operations.
341 */
342static void
343swap_uid(void)
344{
345#ifndef SVR4
346 int euid = geteuid(), uid = getuid();
347
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200348 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200349 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000350 }
351#endif
352}
353
Roland McGrath4bfa6262007-07-05 20:03:16 +0000354#if _LFS64_LARGEFILE
355# define fopen_for_output fopen64
356#else
357# define fopen_for_output fopen
358#endif
359
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200361strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362{
363 FILE *fp;
364
365 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200366 fp = fopen_for_output(path, "w");
367 if (!fp)
368 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200370 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371 return fp;
372}
373
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200374static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000375
376#ifndef _PATH_BSHELL
377# define _PATH_BSHELL "/bin/sh"
378#endif
379
380/*
381 * We cannot use standard popen(3) here because we have to distinguish
382 * popen child process from other processes we trace, and standard popen(3)
383 * does not export its child's pid.
384 */
385static FILE *
386strace_popen(const char *command)
387{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388 FILE *fp;
389 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000390
391 swap_uid();
392 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200393 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200395 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000396
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200397 popen_pid = vfork();
398 if (popen_pid == -1)
399 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200401 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000402 /* child */
403 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200404 if (fds[0] != 0) {
405 if (dup2(fds[0], 0))
406 perror_msg_and_die("dup2");
407 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000408 }
409 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200410 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000411 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200412
413 /* parent */
414 close(fds[0]);
415 swap_uid();
416 fp = fdopen(fds[1], "w");
417 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200418 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200419 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420}
421
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200422static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000423newoutf(struct tcb *tcp)
424{
425 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000426 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000427 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200428 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000429 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000430}
431
Roland McGrath02203312007-06-11 22:06:31 +0000432static void
433startup_attach(void)
434{
435 int tcbi;
436 struct tcb *tcp;
437
438 /*
439 * Block user interruptions as we would leave the traced
440 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200441 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200442 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000443 */
444 if (interactive)
445 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
446
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000447 if (daemonized_tracer) {
448 pid_t pid = fork();
449 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200450 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000451 }
452 if (pid) { /* parent */
453 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200454 * Wait for grandchild to attach to straced process
455 * (grandparent). Grandchild SIGKILLs us after it attached.
456 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000457 * it proceeds to exec the straced program.
458 */
459 pause();
460 _exit(0); /* paranoia */
461 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200462 /* grandchild */
463 /* We will be the tracer process. Remember our new pid: */
464 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000465 }
466
Roland McGrath02203312007-06-11 22:06:31 +0000467 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
468 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200469
Denys Vlasenkod116a732011-09-05 14:01:33 +0200470 /* Is this a process we should attach to, but not yet attached? */
471 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
472 continue; /* no */
473
474 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000475 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200476 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000477
478#ifdef USE_PROCFS
479 if (proc_open(tcp, 1) < 0) {
480 fprintf(stderr, "trouble opening proc file\n");
481 droptcb(tcp);
482 continue;
483 }
484#else /* !USE_PROCFS */
485# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000486 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000487 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000488 DIR *dir;
489
490 sprintf(procdir, "/proc/%d/task", tcp->pid);
491 dir = opendir(procdir);
492 if (dir != NULL) {
493 unsigned int ntid = 0, nerr = 0;
494 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200495
Roland McGrath02203312007-06-11 22:06:31 +0000496 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200497 struct tcb *cur_tcp;
498 int tid;
499
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000500 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000501 continue;
502 tid = atoi(de->d_name);
503 if (tid <= 0)
504 continue;
505 ++ntid;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200506 if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000507 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200508 if (debug)
509 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200510 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200511 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200512 if (debug)
513 fprintf(stderr, "attach to pid %d succeeded\n", tid);
514 cur_tcp = tcp;
515 if (tid != tcp->pid)
516 cur_tcp = alloctcb(tid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200517 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrath02203312007-06-11 22:06:31 +0000518 }
519 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200520 if (interactive) {
521 sigprocmask(SIG_SETMASK, &empty_set, NULL);
522 if (interrupted)
523 goto ret;
524 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
525 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000526 ntid -= nerr;
527 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000528 perror("attach: ptrace(PTRACE_ATTACH, ...)");
529 droptcb(tcp);
530 continue;
531 }
532 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000533 fprintf(stderr, ntid > 1
534? "Process %u attached with %u threads - interrupt to quit\n"
535: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200536 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000537 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200538 if (!(tcp->flags & TCB_STARTUP)) {
539 /* -p PID, we failed to attach to PID itself
540 * but did attach to some of its sibling threads.
541 * Drop PID's tcp.
542 */
543 droptcb(tcp);
544 }
Roland McGrath02203312007-06-11 22:06:31 +0000545 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000546 } /* if (opendir worked) */
547 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200548# endif /* LINUX */
Roland McGrath02203312007-06-11 22:06:31 +0000549 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
550 perror("attach: ptrace(PTRACE_ATTACH, ...)");
551 droptcb(tcp);
552 continue;
553 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200554 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200555 if (debug)
556 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000557
558 if (daemonized_tracer) {
559 /*
560 * It is our grandparent we trace, not a -p PID.
561 * Don't want to just detach on exit, so...
562 */
563 tcp->flags &= ~TCB_ATTACHED;
564 /*
565 * Make parent go away.
566 * Also makes grandparent's wait() unblock.
567 */
568 kill(getppid(), SIGKILL);
569 }
570
Roland McGrath02203312007-06-11 22:06:31 +0000571#endif /* !USE_PROCFS */
572 if (!qflag)
573 fprintf(stderr,
574 "Process %u attached - interrupt to quit\n",
575 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200576 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000577
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200578 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000579 if (interactive)
580 sigprocmask(SIG_SETMASK, &empty_set, NULL);
581}
582
583static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200584startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000585{
586 struct stat statbuf;
587 const char *filename;
588 char pathname[MAXPATHLEN];
589 int pid = 0;
590 struct tcb *tcp;
591
592 filename = argv[0];
593 if (strchr(filename, '/')) {
594 if (strlen(filename) > sizeof pathname - 1) {
595 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200596 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000597 }
598 strcpy(pathname, filename);
599 }
600#ifdef USE_DEBUGGING_EXEC
601 /*
602 * Debuggers customarily check the current directory
603 * first regardless of the path but doing that gives
604 * security geeks a panic attack.
605 */
606 else if (stat(filename, &statbuf) == 0)
607 strcpy(pathname, filename);
608#endif /* USE_DEBUGGING_EXEC */
609 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000610 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000611 int m, n, len;
612
613 for (path = getenv("PATH"); path && *path; path += m) {
614 if (strchr(path, ':')) {
615 n = strchr(path, ':') - path;
616 m = n + 1;
617 }
618 else
619 m = n = strlen(path);
620 if (n == 0) {
621 if (!getcwd(pathname, MAXPATHLEN))
622 continue;
623 len = strlen(pathname);
624 }
625 else if (n > sizeof pathname - 1)
626 continue;
627 else {
628 strncpy(pathname, path, n);
629 len = n;
630 }
631 if (len && pathname[len - 1] != '/')
632 pathname[len++] = '/';
633 strcpy(pathname + len, filename);
634 if (stat(pathname, &statbuf) == 0 &&
635 /* Accept only regular files
636 with some execute bits set.
637 XXX not perfect, might still fail */
638 S_ISREG(statbuf.st_mode) &&
639 (statbuf.st_mode & 0111))
640 break;
641 }
642 }
643 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200644 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000645 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000646 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000647 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200648 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000649 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200650 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
651 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000652 ) {
653 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200654 if (outf != stderr)
655 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000656#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200657# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000658 /* Kludge for SGI, see proc_open for details. */
659 sa.sa_handler = foobar;
660 sa.sa_flags = 0;
661 sigemptyset(&sa.sa_mask);
662 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200663# endif
664# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000665 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200666# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200667 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200668# endif
Roland McGrath02203312007-06-11 22:06:31 +0000669#else /* !USE_PROCFS */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000670 if (!daemonized_tracer) {
671 if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200672 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673 }
674 if (debug)
675 kill(pid, SIGSTOP);
Roland McGrath02203312007-06-11 22:06:31 +0000676 }
Roland McGrath02203312007-06-11 22:06:31 +0000677
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200678 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000679 uid_t run_euid = run_uid;
680 gid_t run_egid = run_gid;
681
682 if (statbuf.st_mode & S_ISUID)
683 run_euid = statbuf.st_uid;
684 if (statbuf.st_mode & S_ISGID)
685 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000686 /*
687 * It is important to set groups before we
688 * lose privileges on setuid.
689 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200690 if (initgroups(username, run_gid) < 0) {
691 perror_msg_and_die("initgroups");
692 }
693 if (setregid(run_gid, run_egid) < 0) {
694 perror_msg_and_die("setregid");
695 }
696 if (setreuid(run_uid, run_euid) < 0) {
697 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000698 }
699 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200700 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000701 setreuid(run_uid, run_uid);
702
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000703 if (!daemonized_tracer) {
704 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200705 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000706 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200707 * the immediately following execve syscall.
708 * Can't do this on NOMMU systems, we are after
709 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000710 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400711 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200712 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000713 } else {
714 struct sigaction sv_sigchld;
715 sigaction(SIGCHLD, NULL, &sv_sigchld);
716 /*
717 * Make sure it is not SIG_IGN, otherwise wait
718 * will not block.
719 */
720 signal(SIGCHLD, SIG_DFL);
721 /*
722 * Wait for grandchild to attach to us.
723 * It kills child after that, and wait() unblocks.
724 */
725 alarm(3);
726 wait(NULL);
727 alarm(0);
728 sigaction(SIGCHLD, &sv_sigchld, NULL);
729 }
Roland McGrath02203312007-06-11 22:06:31 +0000730#endif /* !USE_PROCFS */
731
732 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200733 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000734 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000735
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200736 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200737
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200738 if (!daemonized_tracer) {
739 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200740 if (!strace_vforked)
741 tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
742 else
743 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200744 }
745 else {
746 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
747 strace_tracer_pid = getpid();
748 /* The tracee is our parent: */
749 pid = getppid();
750 tcp = alloctcb(pid);
751 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000752 tcp->flags |= TCB_ATTACHED;
753 }
Roland McGrath02203312007-06-11 22:06:31 +0000754#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000755 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200756 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000757 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200758#endif
Roland McGrath02203312007-06-11 22:06:31 +0000759}
760
Wang Chaob13c0de2010-11-12 17:25:19 +0800761#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000762static void kill_save_errno(pid_t pid, int sig)
763{
764 int saved_errno = errno;
765
766 (void) kill(pid, sig);
767 errno = saved_errno;
768}
769
Wang Chaob13c0de2010-11-12 17:25:19 +0800770/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000771 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800772 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000773 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800774 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000775static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200776test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800777{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000778 int pid, expected_grandchild = 0, found_grandchild = 0;
779 const unsigned int test_options = PTRACE_O_TRACECLONE |
780 PTRACE_O_TRACEFORK |
781 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800782
Denys Vlasenko5d645812011-08-20 12:48:18 +0200783 pid = fork();
784 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000785 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200786 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000787 pid = getpid();
788 if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
789 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
790 __func__);
791 kill(pid, SIGSTOP);
792 if (fork() < 0)
793 perror_msg_and_die("fork");
794 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800795 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000796
797 while (1) {
798 int status, tracee_pid;
799
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000800 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000801 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000802 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000803 if (errno == EINTR)
804 continue;
805 else if (errno == ECHILD)
806 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000807 kill_save_errno(pid, SIGKILL);
808 perror_msg_and_die("%s: unexpected wait result %d",
809 __func__, tracee_pid);
810 }
811 if (WIFEXITED(status)) {
812 if (WEXITSTATUS(status)) {
813 if (tracee_pid != pid)
814 kill_save_errno(pid, SIGKILL);
815 error_msg_and_die("%s: unexpected exit status %u",
816 __func__, WEXITSTATUS(status));
817 }
818 continue;
819 }
820 if (WIFSIGNALED(status)) {
821 if (tracee_pid != pid)
822 kill_save_errno(pid, SIGKILL);
823 error_msg_and_die("%s: unexpected signal %u",
824 __func__, WTERMSIG(status));
825 }
826 if (!WIFSTOPPED(status)) {
827 if (tracee_pid != pid)
828 kill_save_errno(tracee_pid, SIGKILL);
829 kill(pid, SIGKILL);
830 error_msg_and_die("%s: unexpected wait status %x",
831 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000832 }
833 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000834 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000835 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
836 kill_save_errno(tracee_pid, SIGKILL);
837 kill_save_errno(pid, SIGKILL);
838 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800839 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000840 continue;
841 }
842 switch (WSTOPSIG(status)) {
843 case SIGSTOP:
844 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
845 && errno != EINVAL && errno != EIO)
846 perror_msg("PTRACE_SETOPTIONS");
847 break;
848 case SIGTRAP:
849 if (status >> 16 == PTRACE_EVENT_FORK) {
850 long msg = 0;
851
852 if (ptrace(PTRACE_GETEVENTMSG, pid,
853 NULL, (long) &msg) == 0)
854 expected_grandchild = msg;
855 }
856 break;
857 }
858 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
859 kill_save_errno(pid, SIGKILL);
860 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800861 }
862 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000863 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200864 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000865 if (debug)
866 fprintf(stderr, "ptrace_setoptions = %#x\n",
867 ptrace_setoptions);
868 return;
869 }
870 error_msg("Test for PTRACE_O_TRACECLONE failed, "
871 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800872}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200873
874/*
875 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
876 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
877 * and then see whether it will stop with (SIGTRAP | 0x80).
878 *
879 * Use of this option enables correct handling of user-generated SIGTRAPs,
880 * and SIGTRAPs generated by special instructions such as int3 on x86:
881 * _start: .globl _start
882 * int3
883 * movl $42, %ebx
884 * movl $1, %eax
885 * int $0x80
886 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
887 */
888static void
889test_ptrace_setoptions_for_all(void)
890{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000891 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
892 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200893 int pid;
894 int it_worked = 0;
895
896 pid = fork();
897 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200898 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200899
900 if (pid == 0) {
901 pid = getpid();
902 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200903 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000904 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
905 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200906 kill(pid, SIGSTOP);
907 _exit(0); /* parent should see entry into this syscall */
908 }
909
910 while (1) {
911 int status, tracee_pid;
912
913 errno = 0;
914 tracee_pid = wait(&status);
915 if (tracee_pid <= 0) {
916 if (errno == EINTR)
917 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000918 kill_save_errno(pid, SIGKILL);
919 perror_msg_and_die("%s: unexpected wait result %d",
920 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200921 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200922 if (WIFEXITED(status)) {
923 if (WEXITSTATUS(status) == 0)
924 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000925 error_msg_and_die("%s: unexpected exit status %u",
926 __func__, WEXITSTATUS(status));
927 }
928 if (WIFSIGNALED(status)) {
929 error_msg_and_die("%s: unexpected signal %u",
930 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200931 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200932 if (!WIFSTOPPED(status)) {
933 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000934 error_msg_and_die("%s: unexpected wait status %x",
935 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200936 }
937 if (WSTOPSIG(status) == SIGSTOP) {
938 /*
939 * We don't check "options aren't accepted" error.
940 * If it happens, we'll never get (SIGTRAP | 0x80),
941 * and thus will decide to not use the option.
942 * IOW: the outcome of the test will be correct.
943 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000944 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
945 && errno != EINVAL && errno != EIO)
946 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200947 }
948 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
949 it_worked = 1;
950 }
951 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000952 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200953 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200954 }
955 }
956
957 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200958 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200959 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200960 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200961 fprintf(stderr, "ptrace_setoptions = %#x\n",
962 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200963 return;
964 }
965
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000966 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
967 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200968}
Wang Chaob13c0de2010-11-12 17:25:19 +0800969#endif
970
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100971/* Noinline: don't want main to have struct utsname permanently on stack */
972static void __attribute__ ((noinline))
973get_os_release(void)
974{
975 struct utsname u;
976 if (uname(&u) < 0)
977 perror_msg_and_die("uname");
978 os_release = strdup(u.release);
979 if (!os_release)
980 die_out_of_memory();
981}
982
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000984main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 struct tcb *tcp;
987 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +0000988 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 struct sigaction sa;
990
Dmitry V. Levin08b623e2007-10-08 21:04:41 +0000991 progname = argv[0] ? argv[0] : "strace";
992
Denys Vlasenko75422762011-05-27 14:36:01 +0200993 strace_tracer_pid = getpid();
994
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100995 get_os_release();
996
Roland McGrathee9d4352002-12-18 04:16:10 +0000997 /* Allocate the initial tcbtab. */
998 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +0200999 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001000 if (!tcbtab)
1001 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001002 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001003 if (!tcp)
1004 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001005 for (c = 0; c < tcbtabsize; c++)
1006 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001007
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001009 set_sortby(DEFAULT_SORTBY);
1010 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 qualify("trace=all");
1012 qualify("abbrev=all");
1013 qualify("verbose=all");
1014 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001016 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001017#ifndef USE_PROCFS
1018 "D"
1019#endif
Grant Edwards8a082772011-04-07 20:25:40 +00001020 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001021 switch (c) {
1022 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001023 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001024 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001025 }
1026 cflag = CFLAG_ONLY_STATS;
1027 break;
1028 case 'C':
1029 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001030 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001031 }
1032 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 break;
1034 case 'd':
1035 debug++;
1036 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001037#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001038 case 'D':
1039 daemonized_tracer = 1;
1040 break;
1041#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001042 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001043 optF = 1;
1044 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 case 'f':
1046 followfork++;
1047 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001048 case 'h':
1049 usage(stdout, 0);
1050 break;
1051 case 'i':
1052 iflag++;
1053 break;
1054 case 'q':
1055 qflag++;
1056 break;
1057 case 'r':
1058 rflag++;
1059 tflag++;
1060 break;
1061 case 't':
1062 tflag++;
1063 break;
1064 case 'T':
1065 dtime++;
1066 break;
1067 case 'x':
1068 xflag++;
1069 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001070 case 'y':
1071 show_fd_path = 1;
1072 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 case 'v':
1074 qualify("abbrev=none");
1075 break;
1076 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001077 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 exit(0);
1079 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001080 case 'z':
1081 not_failing_only = 1;
1082 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083 case 'a':
1084 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001085 if (acolumn < 0)
1086 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 break;
1088 case 'e':
1089 qualify(optarg);
1090 break;
1091 case 'o':
1092 outfname = strdup(optarg);
1093 break;
1094 case 'O':
1095 set_overhead(atoi(optarg));
1096 break;
1097 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001098 pid = atoi(optarg);
1099 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001100 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 break;
1102 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001103 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001104 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105 break;
1106 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001107 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 tcp->flags |= TCB_ATTACHED;
1109 pflag_seen++;
1110 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001111 case 'P':
1112 tracing_paths = 1;
1113 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001114 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001115 }
1116 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 case 's':
1118 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001119 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001120 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001121 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 break;
1123 case 'S':
1124 set_sortby(optarg);
1125 break;
1126 case 'u':
1127 username = strdup(optarg);
1128 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001129 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001130 if (putenv(optarg) < 0)
1131 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001132 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 default:
1134 usage(stderr, 1);
1135 break;
1136 }
1137 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001138 argv += optind;
1139 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140
Denys Vlasenko102ec492011-08-25 01:27:59 +02001141 acolumn_spaces = malloc(acolumn + 1);
1142 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001143 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001144 memset(acolumn_spaces, ' ', acolumn);
1145 acolumn_spaces[acolumn] = '\0';
1146
Denys Vlasenko837399a2012-01-24 11:37:03 +01001147 /* Must have PROG [ARGS], or -p PID. Not both. */
1148 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001149 usage(stderr, 1);
1150
Wang Chaod322a4b2010-08-05 14:30:11 +08001151 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001152 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001153 }
1154
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001155 if (!followfork)
1156 followfork = optF;
1157
Roland McGrathcb9def62006-04-25 07:48:03 +00001158 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001159 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001160 }
1161
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 /* See if they want to run as another user. */
1163 if (username != NULL) {
1164 struct passwd *pent;
1165
1166 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001167 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001169 pent = getpwnam(username);
1170 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001171 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 }
1173 run_uid = pent->pw_uid;
1174 run_gid = pent->pw_gid;
1175 }
1176 else {
1177 run_uid = getuid();
1178 run_gid = getgid();
1179 }
1180
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001181#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001182 if (followfork)
1183 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001184 test_ptrace_setoptions_for_all();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001185#endif
1186
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 /* Check if they want to redirect the output. */
1188 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001189 /* See if they want to pipe the output. */
1190 if (outfname[0] == '|' || outfname[0] == '!') {
1191 /*
1192 * We can't do the <outfname>.PID funny business
1193 * when using popen, so prohibit it.
1194 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001195 if (followfork > 1)
1196 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1197 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001198 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001199 else if (followfork <= 1)
1200 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 }
1202
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001203 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001204 char *buf = malloc(BUFSIZ);
1205 if (!buf)
1206 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001208 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001209 if (outfname && argv[0]) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001212 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001213
Roland McGrath54cc1c82007-11-03 23:34:11 +00001214 /* Valid states here:
Denys Vlasenko837399a2012-01-24 11:37:03 +01001215 argv[0] pflag_seen outfname interactive
1216 yes 0 0 1
1217 no 1 0 1
1218 yes 0 1 0
1219 no 1 1 1
Roland McGrath54cc1c82007-11-03 23:34:11 +00001220 */
1221
1222 /* STARTUP_CHILD must be called before the signal handlers get
1223 installed below as they are inherited into the spawned process.
1224 Also we do not need to be protected by them as during interruption
1225 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001226 if (argv[0])
1227 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 sigemptyset(&empty_set);
1230 sigemptyset(&blocked_set);
1231 sa.sa_handler = SIG_IGN;
1232 sigemptyset(&sa.sa_mask);
1233 sa.sa_flags = 0;
1234 sigaction(SIGTTOU, &sa, NULL);
1235 sigaction(SIGTTIN, &sa, NULL);
Denys Vlasenko837399a2012-01-24 11:37:03 +01001236 /* In interactive mode (if no -o OUTFILE, or -p PID is used),
1237 * fatal signals are blocked across syscall waits, and acted on
1238 * in between. In non-interactive mode, signals are ignored.
1239 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001240 if (interactive) {
1241 sigaddset(&blocked_set, SIGHUP);
1242 sigaddset(&blocked_set, SIGINT);
1243 sigaddset(&blocked_set, SIGQUIT);
1244 sigaddset(&blocked_set, SIGPIPE);
1245 sigaddset(&blocked_set, SIGTERM);
1246 sa.sa_handler = interrupt;
1247#ifdef SUNOS4
1248 /* POSIX signals on sunos4.1 are a little broken. */
1249 sa.sa_flags = SA_INTERRUPT;
1250#endif /* SUNOS4 */
1251 }
1252 sigaction(SIGHUP, &sa, NULL);
1253 sigaction(SIGINT, &sa, NULL);
1254 sigaction(SIGQUIT, &sa, NULL);
1255 sigaction(SIGPIPE, &sa, NULL);
1256 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001257#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001258 sa.sa_handler = reaper;
1259 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001260#else
1261 /* Make sure SIGCHLD has the default action so that waitpid
1262 definitely works without losing track of children. The user
1263 should not have given us a bogus state to inherit, but he might
1264 have. Arguably we should detect SIG_IGN here and pass it on
1265 to children, but probably noone really needs that. */
1266 sa.sa_handler = SIG_DFL;
1267 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001268#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001270 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001271 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001272
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 if (trace() < 0)
1274 exit(1);
1275 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001276 fflush(NULL);
1277 if (exit_code > 0xff) {
1278 /* Child was killed by a signal, mimic that. */
1279 exit_code &= 0xff;
1280 signal(exit_code, SIG_DFL);
1281 raise(exit_code);
1282 /* Paranoia - what if this signal is not fatal?
1283 Exit with 128 + signo then. */
1284 exit_code += 128;
1285 }
1286 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287}
1288
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001289static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001290expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001291{
1292 /* Allocate some more TCBs and expand the table.
1293 We don't want to relocate the TCBs because our
1294 callers have pointers and it would be a pain.
1295 So tcbtab is a table of pointers. Since we never
1296 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001297 int i = tcbtabsize;
1298 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1299 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001300 if (!newtab || !newtcbs)
1301 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001302 tcbtabsize *= 2;
1303 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001304 while (i < tcbtabsize)
1305 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001306}
1307
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001309alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310{
1311 int i;
1312 struct tcb *tcp;
1313
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001314 if (nprocs == tcbtabsize)
1315 expand_tcbtab();
1316
Roland McGrathee9d4352002-12-18 04:16:10 +00001317 for (i = 0; i < tcbtabsize; i++) {
1318 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001320 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001322 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001324#if SUPPORTED_PERSONALITIES > 1
1325 tcp->currpers = current_personality;
1326#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001327#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001329#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001331 if (debug)
1332 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001333 if (command_options_parsed)
1334 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 return tcp;
1336 }
1337 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001338 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339}
1340
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001341#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001343proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344{
1345 char proc[32];
1346 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001347#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001348 int i;
1349 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350 sigset_t signals;
1351 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001352#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353#ifndef HAVE_POLLABLE_PROCFS
1354 static int last_pfd;
1355#endif
1356
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001357#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001358 /* Open the process pseudo-files in /proc. */
1359 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001360 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1361 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 perror("strace: open(\"/proc/...\", ...)");
1363 return -1;
1364 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001365 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001366 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001367 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1368 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001369 perror("strace: open(\"/proc/...\", ...)");
1370 return -1;
1371 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001372 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001373 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001374 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1375 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001376 perror("strace: open(\"/proc/...\", ...)");
1377 return -1;
1378 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001379 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001380#else
1381 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001382# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001384 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001385# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001386 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001387 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001388# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001389 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001390 perror("strace: open(\"/proc/...\", ...)");
1391 return -1;
1392 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001393 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001394#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001395#ifdef FREEBSD
1396 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001397 tcp->pfd_reg = open(proc, O_RDONLY);
1398 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001399 perror("strace: open(\"/proc/.../regs\", ...)");
1400 return -1;
1401 }
1402 if (cflag) {
1403 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001404 tcp->pfd_status = open(proc, O_RDONLY);
1405 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001406 perror("strace: open(\"/proc/.../status\", ...)");
1407 return -1;
1408 }
1409 } else
1410 tcp->pfd_status = -1;
1411#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001412 rebuild_pollv();
1413 if (!attaching) {
1414 /*
1415 * Wait for the child to pause. Because of a race
1416 * condition we have to poll for the event.
1417 */
1418 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001419 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001420 perror("strace: PIOCSTATUS");
1421 return -1;
1422 }
1423 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001424 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001425 }
1426 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001427#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001428 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001429 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001430 perror("strace: PIOCSTOP");
1431 return -1;
1432 }
Roland McGrath553a6092002-12-16 20:40:39 +00001433#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001434#ifdef PIOCSET
1435 /* Set Run-on-Last-Close. */
1436 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001437 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 perror("PIOCSET PR_RLC");
1439 return -1;
1440 }
1441 /* Set or Reset Inherit-on-Fork. */
1442 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001443 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 perror("PIOC{SET,RESET} PR_FORK");
1445 return -1;
1446 }
1447#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001448#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1450 perror("PIOCSRLC");
1451 return -1;
1452 }
1453 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1454 perror("PIOC{S,R}FORK");
1455 return -1;
1456 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001457#else /* FREEBSD */
1458 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1459 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1460 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001461 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001462 }
1463 arg &= ~PF_LINGER;
1464 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001465 perror("PIOCSFL");
1466 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001467 }
1468#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001470#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001471 /* Enable all syscall entries we care about. */
1472 premptyset(&syscalls);
1473 for (i = 1; i < MAX_QUALS; ++i) {
1474 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001475 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001476 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001477 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001478 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001479 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001480#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001481 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001482#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001483#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001484 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001485#endif
1486#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001487 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001488#endif
1489#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001490 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001491#endif
1492 }
1493 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 perror("PIOCSENTRY");
1495 return -1;
1496 }
John Hughes19e49982001-10-19 08:59:12 +00001497 /* Enable the syscall exits. */
1498 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 perror("PIOSEXIT");
1500 return -1;
1501 }
John Hughes19e49982001-10-19 08:59:12 +00001502 /* Enable signals we care about. */
1503 premptyset(&signals);
1504 for (i = 1; i < MAX_QUALS; ++i) {
1505 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001506 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001507 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001508 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 perror("PIOCSTRACE");
1510 return -1;
1511 }
John Hughes19e49982001-10-19 08:59:12 +00001512 /* Enable faults we care about */
1513 premptyset(&faults);
1514 for (i = 1; i < MAX_QUALS; ++i) {
1515 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001516 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001517 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001518 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 perror("PIOCSFAULT");
1520 return -1;
1521 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001522#else /* FREEBSD */
1523 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001524 arg = S_SIG | S_SCE | S_SCX;
1525 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001526 perror("PIOCBIS");
1527 return -1;
1528 }
1529#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 if (!attaching) {
1531#ifdef MIPS
1532 /*
1533 * The SGI PRSABORT doesn't work for pause() so
1534 * we send it a caught signal to wake it up.
1535 */
1536 kill(tcp->pid, SIGINT);
1537#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001538#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001540 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001541 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542 perror("PIOCRUN");
1543 return -1;
1544 }
Roland McGrath553a6092002-12-16 20:40:39 +00001545#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001546#endif /* !MIPS*/
1547#ifdef FREEBSD
1548 /* wake up the child if it received the SIGSTOP */
1549 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001550#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 for (;;) {
1552 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001553 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001554 perror("PIOCWSTOP");
1555 return -1;
1556 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001557 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001558 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001559 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001560 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 break;
1562 }
1563 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001564#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001565 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001566 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1567#else
1568 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1569#endif
1570 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571 perror("PIOCRUN");
1572 return -1;
1573 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001574#ifdef FREEBSD
1575 /* handle the case where we "opened" the child before
1576 it did the kill -STOP */
1577 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1578 tcp->status.PR_WHAT == SIGSTOP)
1579 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001580#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 }
1582 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001583#ifdef FREEBSD
1584 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001585 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001586 /* We are attaching to an already running process.
1587 * Try to figure out the state of the process in syscalls,
1588 * to handle the first event well.
1589 * This is done by having a look at the "wchan" property of the
1590 * process, which tells where it is stopped (if it is). */
1591 FILE * status;
1592 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001593
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001594 sprintf(proc, "/proc/%d/status", tcp->pid);
1595 status = fopen(proc, "r");
1596 if (status &&
1597 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1598 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1599 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1600 strcmp(wchan, "stopevent")) {
1601 /* The process is asleep in the middle of a syscall.
1602 Fake the syscall entry event */
1603 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1604 tcp->status.PR_WHY = PR_SYSENTRY;
1605 trace_syscall(tcp);
1606 }
1607 if (status)
1608 fclose(status);
1609 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001610 }
1611#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612#ifndef HAVE_POLLABLE_PROCFS
1613 if (proc_poll_pipe[0] != -1)
1614 proc_poller(tcp->pfd);
1615 else if (nprocs > 1) {
1616 proc_poll_open();
1617 proc_poller(last_pfd);
1618 proc_poller(tcp->pfd);
1619 }
1620 last_pfd = tcp->pfd;
1621#endif /* !HAVE_POLLABLE_PROCFS */
1622 return 0;
1623}
1624
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001625#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001627static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001628pid2tcb(int pid)
1629{
1630 int i;
1631
1632 if (pid <= 0)
1633 return NULL;
1634
1635 for (i = 0; i < tcbtabsize; i++) {
1636 struct tcb *tcp = tcbtab[i];
1637 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1638 return tcp;
1639 }
1640
1641 return NULL;
1642}
1643
1644#ifdef USE_PROCFS
1645
1646static struct tcb *
1647first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648{
1649 int i;
1650 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001651 for (i = 0; i < tcbtabsize; i++) {
1652 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 if (tcp->flags & TCB_INUSE)
1654 return tcp;
1655 }
1656 return NULL;
1657}
1658
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001660pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661{
1662 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663
Roland McGrathca16be82003-01-10 19:55:28 +00001664 for (i = 0; i < tcbtabsize; i++) {
1665 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 if (tcp->pfd != pfd)
1667 continue;
1668 if (tcp->flags & TCB_INUSE)
1669 return tcp;
1670 }
1671 return NULL;
1672}
1673
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001674#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675
1676void
Denys Vlasenko12014262011-05-30 14:00:14 +02001677droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678{
1679 if (tcp->pid == 0)
1680 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001681
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001683 if (debug)
1684 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001685
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001686#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 if (tcp->pfd != -1) {
1688 close(tcp->pfd);
1689 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001690# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001691 if (tcp->pfd_reg != -1) {
1692 close(tcp->pfd_reg);
1693 tcp->pfd_reg = -1;
1694 }
1695 if (tcp->pfd_status != -1) {
1696 close(tcp->pfd_status);
1697 tcp->pfd_status = -1;
1698 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001699# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001700 tcp->flags = 0; /* rebuild_pollv needs it */
1701 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001703#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001704
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001705 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001707
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001708 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001709}
1710
Roland McGrath0a463882007-07-05 18:43:16 +00001711/* detach traced process; continue with sig
1712 Never call DETACH twice on the same process as both unattached and
1713 attached-unstopped processes give the same ESRCH. For unattached process we
1714 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715
1716static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001717detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718{
1719 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001720#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001721 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001722#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723
1724 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001725 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726
1727#ifdef LINUX
1728 /*
1729 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001730 * before detaching. Arghh. We go through hoops
1731 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001733#if defined(SPARC)
1734#undef PTRACE_DETACH
1735#define PTRACE_DETACH PTRACE_SUNDETACH
1736#endif
Roland McGrath02203312007-06-11 22:06:31 +00001737 /*
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001738 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1739 * We must catch exactly one as otherwise the detached process
1740 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001741 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001742 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001743 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001744 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001746 }
1747 else if (errno != ESRCH) {
1748 /* Shouldn't happen. */
1749 perror("detach: ptrace(PTRACE_DETACH, ...)");
1750 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001751 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001752 if (errno != ESRCH)
1753 perror("detach: checking sanity");
1754 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001755 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001756 if (errno != ESRCH)
1757 perror("detach: stopping child");
1758 }
Roland McGrath02203312007-06-11 22:06:31 +00001759 else
1760 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001761 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001763#ifdef __WALL
1764 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1765 if (errno == ECHILD) /* Already gone. */
1766 break;
1767 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001768 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001769 break;
1770 }
1771#endif /* __WALL */
1772 /* No __WALL here. */
1773 if (waitpid(tcp->pid, &status, 0) < 0) {
1774 if (errno != ECHILD) {
1775 perror("detach: waiting");
1776 break;
1777 }
1778#ifdef __WCLONE
1779 /* If no processes, try clones. */
1780 if (wait4(tcp->pid, &status, __WCLONE,
1781 NULL) < 0) {
1782 if (errno != ECHILD)
1783 perror("detach: waiting");
1784 break;
1785 }
1786#endif /* __WCLONE */
1787 }
1788#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001789 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001790#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001791 if (!WIFSTOPPED(status)) {
1792 /* Au revoir, mon ami. */
1793 break;
1794 }
1795 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001796 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001797 break;
1798 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001799 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001800 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001801 : WSTOPSIG(status));
1802 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001804 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001805 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001806#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001807
1808#if defined(SUNOS4)
1809 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001810 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001811#endif /* SUNOS4 */
1812
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813 if (!qflag)
1814 fprintf(stderr, "Process %u detached\n", tcp->pid);
1815
1816 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001817
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818 return error;
1819}
1820
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001821#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001823static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824{
1825 int pid;
1826 int status;
1827
1828 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829 }
1830}
1831
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001832#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833
1834static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001835cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001836{
1837 int i;
1838 struct tcb *tcp;
1839
Roland McGrathee9d4352002-12-18 04:16:10 +00001840 for (i = 0; i < tcbtabsize; i++) {
1841 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001842 if (!(tcp->flags & TCB_INUSE))
1843 continue;
1844 if (debug)
1845 fprintf(stderr,
1846 "cleanup: looking at pid %u\n", tcp->pid);
1847 if (tcp_last &&
1848 (!outfname || followfork < 2 || tcp_last == tcp)) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001849 tprints(" <unfinished ...>");
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001850 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 }
1852 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001853 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001854 else {
1855 kill(tcp->pid, SIGCONT);
1856 kill(tcp->pid, SIGTERM);
1857 }
1858 }
1859 if (cflag)
1860 call_summary(outf);
1861}
1862
1863static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001864interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865{
1866 interrupted = 1;
1867}
1868
1869#ifndef HAVE_STRERROR
1870
Roland McGrath6d2b3492002-12-30 00:51:30 +00001871#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872extern int sys_nerr;
1873extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001874#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875
1876const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001877strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001878{
1879 static char buf[64];
1880
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001881 if (err_no < 1 || err_no >= sys_nerr) {
1882 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001883 return buf;
1884 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001885 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886}
1887
1888#endif /* HAVE_STERRROR */
1889
1890#ifndef HAVE_STRSIGNAL
1891
Roland McGrath8f474e02003-01-14 07:53:33 +00001892#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001893extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001894#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001895#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1896extern char *_sys_siglist[];
1897#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898
1899const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001900strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001901{
1902 static char buf[64];
1903
1904 if (sig < 1 || sig >= NSIG) {
1905 sprintf(buf, "Unknown signal %d", sig);
1906 return buf;
1907 }
1908#ifdef HAVE__SYS_SIGLIST
1909 return _sys_siglist[sig];
1910#else
1911 return sys_siglist[sig];
1912#endif
1913}
1914
1915#endif /* HAVE_STRSIGNAL */
1916
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001917#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001918
1919static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001920rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921{
1922 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02001924 free(pollv);
1925 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001926 if (!pollv)
1927 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00001928
Roland McGrathca16be82003-01-10 19:55:28 +00001929 for (i = j = 0; i < tcbtabsize; i++) {
1930 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931 if (!(tcp->flags & TCB_INUSE))
1932 continue;
1933 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001934 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001935 j++;
1936 }
1937 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001938 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939 }
1940}
1941
1942#ifndef HAVE_POLLABLE_PROCFS
1943
1944static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001945proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947 int i;
1948
1949 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001950 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001951 }
1952 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001953 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954 }
1955}
1956
1957static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001958proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959{
1960 int i;
1961 int n;
1962 struct proc_pollfd pollinfo;
1963
Denys Vlasenko5d645812011-08-20 12:48:18 +02001964 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
1965 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 return n;
1967 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001968 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969 }
1970 for (i = 0; i < nprocs; i++) {
1971 if (pollv[i].fd == pollinfo.fd)
1972 pollv[i].revents = pollinfo.revents;
1973 else
1974 pollv[i].revents = 0;
1975 }
1976 poller_pid = pollinfo.pid;
1977 return 1;
1978}
1979
1980static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001981wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982{
1983}
1984
1985static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001986proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001987{
1988 struct proc_pollfd pollinfo;
1989 struct sigaction sa;
1990 sigset_t blocked_set, empty_set;
1991 int i;
1992 int n;
1993 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001994#ifdef FREEBSD
1995 struct procfs_status pfs;
1996#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997
1998 switch (fork()) {
1999 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002000 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001 case 0:
2002 break;
2003 default:
2004 return;
2005 }
2006
2007 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2008 sa.sa_flags = 0;
2009 sigemptyset(&sa.sa_mask);
2010 sigaction(SIGHUP, &sa, NULL);
2011 sigaction(SIGINT, &sa, NULL);
2012 sigaction(SIGQUIT, &sa, NULL);
2013 sigaction(SIGPIPE, &sa, NULL);
2014 sigaction(SIGTERM, &sa, NULL);
2015 sa.sa_handler = wakeup_handler;
2016 sigaction(SIGUSR1, &sa, NULL);
2017 sigemptyset(&blocked_set);
2018 sigaddset(&blocked_set, SIGUSR1);
2019 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2020 sigemptyset(&empty_set);
2021
2022 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002023 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 }
2025 n = rl.rlim_cur;
2026 for (i = 0; i < n; i++) {
2027 if (i != pfd && i != proc_poll_pipe[1])
2028 close(i);
2029 }
2030
2031 pollinfo.fd = pfd;
2032 pollinfo.pid = getpid();
2033 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002034#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002035 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2036#else
2037 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2038#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002039 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 switch (errno) {
2041 case EINTR:
2042 continue;
2043 case EBADF:
2044 pollinfo.revents = POLLERR;
2045 break;
2046 case ENOENT:
2047 pollinfo.revents = POLLHUP;
2048 break;
2049 default:
2050 perror("proc_poller: PIOCWSTOP");
2051 }
2052 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2053 _exit(0);
2054 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002055 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002056 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2057 sigsuspend(&empty_set);
2058 }
2059}
2060
2061#endif /* !HAVE_POLLABLE_PROCFS */
2062
2063static int
2064choose_pfd()
2065{
2066 int i, j;
2067 struct tcb *tcp;
2068
2069 static int last;
2070
2071 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002072 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002073 /*
2074 * The previous process is ready to run again. We'll
2075 * let it do so if it is currently in a syscall. This
2076 * heuristic improves the readability of the trace.
2077 */
2078 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002079 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002080 return pollv[last].fd;
2081 }
2082
2083 for (i = 0; i < nprocs; i++) {
2084 /* Let competing children run round robin. */
2085 j = (i + last + 1) % nprocs;
2086 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2087 tcp = pfd2tcb(pollv[j].fd);
2088 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002089 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 }
2091 droptcb(tcp);
2092 return -1;
2093 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002094 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095 last = j;
2096 return pollv[j].fd;
2097 }
2098 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002099 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100}
2101
2102static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002103trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002105#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002106 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002107#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002108 struct tcb *tcp;
2109 int pfd;
2110 int what;
2111 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002112 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002113
2114 for (;;) {
2115 if (interactive)
2116 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2117
2118 if (nprocs == 0)
2119 break;
2120
2121 switch (nprocs) {
2122 case 1:
2123#ifndef HAVE_POLLABLE_PROCFS
2124 if (proc_poll_pipe[0] == -1) {
2125#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002126 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 if (!tcp)
2128 continue;
2129 pfd = tcp->pfd;
2130 if (pfd == -1)
2131 continue;
2132 break;
2133#ifndef HAVE_POLLABLE_PROCFS
2134 }
2135 /* fall through ... */
2136#endif /* !HAVE_POLLABLE_PROCFS */
2137 default:
2138#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002139#ifdef POLL_HACK
2140 /* On some systems (e.g. UnixWare) we get too much ugly
2141 "unfinished..." stuff when multiple proceses are in
2142 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002143
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002144 if (in_syscall) {
2145 struct pollfd pv;
2146 tcp = in_syscall;
2147 in_syscall = NULL;
2148 pv.fd = tcp->pfd;
2149 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002150 what = poll(&pv, 1, 1);
2151 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002152 if (interrupted)
2153 return 0;
2154 continue;
2155 }
2156 else if (what == 1 && pv.revents & POLLWANT) {
2157 goto FOUND;
2158 }
2159 }
2160#endif
2161
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162 if (poll(pollv, nprocs, INFTIM) < 0) {
2163 if (interrupted)
2164 return 0;
2165 continue;
2166 }
2167#else /* !HAVE_POLLABLE_PROCFS */
2168 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2169 if (interrupted)
2170 return 0;
2171 continue;
2172 }
2173#endif /* !HAVE_POLLABLE_PROCFS */
2174 pfd = choose_pfd();
2175 if (pfd == -1)
2176 continue;
2177 break;
2178 }
2179
2180 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002181 tcp = pfd2tcb(pfd);
2182 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002183 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 }
John Hughesb6643082002-05-23 11:02:22 +00002185#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002186 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002187#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002188 /* Get the status of the process. */
2189 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002190#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002191 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002192#else /* FREEBSD */
2193 /* Thanks to some scheduling mystery, the first poller
2194 sometimes waits for the already processed end of fork
2195 event. Doing a non blocking poll here solves the problem. */
2196 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002197 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002198 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002199 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002200#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002201 ioctl_errno = errno;
2202#ifndef HAVE_POLLABLE_PROCFS
2203 if (proc_poll_pipe[0] != -1) {
2204 if (ioctl_result < 0)
2205 kill(poller_pid, SIGKILL);
2206 else
2207 kill(poller_pid, SIGUSR1);
2208 }
2209#endif /* !HAVE_POLLABLE_PROCFS */
2210 }
2211 if (interrupted)
2212 return 0;
2213
2214 if (interactive)
2215 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2216
2217 if (ioctl_result < 0) {
2218 /* Find out what happened if it failed. */
2219 switch (ioctl_errno) {
2220 case EINTR:
2221 case EBADF:
2222 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002223#ifdef FREEBSD
2224 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002225#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002226 case ENOENT:
2227 droptcb(tcp);
2228 continue;
2229 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002230 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 }
2232 }
2233
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002234#ifdef FREEBSD
2235 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2236 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002237 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002238 continue;
2239 }
Roland McGrath553a6092002-12-16 20:40:39 +00002240#endif
2241
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002242 /* clear the just started flag */
2243 tcp->flags &= ~TCB_STARTUP;
2244
2245 /* set current output file */
2246 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002247 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002248
2249 if (cflag) {
2250 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002251#ifdef FREEBSD
2252 char buf[1024];
2253 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002254
Denys Vlasenko5d645812011-08-20 12:48:18 +02002255 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2256 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002257 buf[len] = '\0';
2258 sscanf(buf,
2259 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2260 &stime.tv_sec, &stime.tv_usec);
2261 } else
2262 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002263#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002264 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2265 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002266#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002267 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2268 tcp->stime = stime;
2269 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002270 what = tcp->status.PR_WHAT;
2271 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002272#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002273 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002274 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2275 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002276 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002277 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002278 }
2279 }
2280 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002281#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002282 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002283#ifdef POLL_HACK
2284 in_syscall = tcp;
2285#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002286 case PR_SYSEXIT:
2287 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002288 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002289 }
2290 break;
2291 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002292 if (cflag != CFLAG_ONLY_STATS
2293 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294 printleader(tcp);
2295 tprintf("--- %s (%s) ---",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002296 signame(what), strsignal(what));
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002297 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002298#ifdef PR_INFO
2299 if (tcp->status.PR_INFO.si_signo == what) {
2300 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002301 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002302 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002303 printtrailer();
John Hughes58265892001-10-18 15:13:53 +00002304 }
2305#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002306 }
2307 break;
2308 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002309 if (cflag != CFLAGS_ONLY_STATS
2310 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002311 printleader(tcp);
2312 tprintf("=== FAULT %d ===", what);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002313 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314 }
2315 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002316#ifdef FREEBSD
2317 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002318 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002319#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002320 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002321 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002322 break;
2323 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002324 /* Remember current print column before continuing. */
2325 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002326 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002327#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002328 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002329#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002330 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002331#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002332 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002333 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 }
2335 }
2336 return 0;
2337}
2338
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002339#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340
Roland McGratheb9e2e82009-06-02 16:49:22 -07002341static int
2342trace()
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002344#ifdef LINUX
2345 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002346 struct rusage *rup = cflag ? &ru : NULL;
2347# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002348 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002349# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002350#endif /* LINUX */
2351
Roland McGratheb9e2e82009-06-02 16:49:22 -07002352 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002353 int pid;
2354 int wait_errno;
2355 int status, sig;
2356 struct tcb *tcp;
2357 unsigned event;
2358
Denys Vlasenko222713a2009-03-17 14:29:59 +00002359 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002360 return 0;
2361 if (interactive)
2362 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002364# ifdef __WALL
2365 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002366 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002367 /* this kernel does not support __WALL */
2368 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002369 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002370 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002371 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002372 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002373 pid = wait4(-1, &status, __WCLONE, rup);
2374 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002375 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002376 }
2377 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002378# else
2379 pid = wait4(-1, &status, 0, rup);
2380# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002381#endif /* LINUX */
2382#ifdef SUNOS4
2383 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002384#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002386 if (interactive)
2387 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002389 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002390 switch (wait_errno) {
2391 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002393 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394 /*
2395 * We would like to verify this case
2396 * but sometimes a race in Solbourne's
2397 * version of SunOS sometimes reports
2398 * ECHILD before sending us SIGCHILD.
2399 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002400 return 0;
2401 default:
2402 errno = wait_errno;
2403 perror("strace: wait");
2404 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002405 }
2406 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002407 if (pid == popen_pid) {
2408 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002409 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002410 continue;
2411 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002412
2413 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002414 if (debug) {
2415 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2416#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002417 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002418 static const char *const event_names[] = {
2419 [PTRACE_EVENT_CLONE] = "CLONE",
2420 [PTRACE_EVENT_FORK] = "FORK",
2421 [PTRACE_EVENT_VFORK] = "VFORK",
2422 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2423 [PTRACE_EVENT_EXEC] = "EXEC",
2424 [PTRACE_EVENT_EXIT] = "EXIT",
2425 };
2426 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002427 if (event < ARRAY_SIZE(event_names))
2428 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002429 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002430 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002431 e = buf;
2432 }
2433 fprintf(stderr, " PTRACE_EVENT_%s", e);
2434 }
2435#endif
2436 strcpy(buf, "???");
2437 if (WIFSIGNALED(status))
2438#ifdef WCOREDUMP
2439 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2440 WCOREDUMP(status) ? "core," : "",
2441 signame(WTERMSIG(status)));
2442#else
2443 sprintf(buf, "WIFSIGNALED,sig=%s",
2444 signame(WTERMSIG(status)));
2445#endif
2446 if (WIFEXITED(status))
2447 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2448 if (WIFSTOPPED(status))
2449 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002450#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002451 if (WIFCONTINUED(status))
2452 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002453#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002454 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2455 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002456
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002457 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002458 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002459
2460#ifdef LINUX
2461 /* Under Linux, execve changes pid to thread leader's pid,
2462 * and we see this changed pid on EVENT_EXEC and later,
2463 * execve sysexit. Leader "disappears" without exit
2464 * notification. Let user know that, drop leader's tcb,
2465 * and fix up pid in execve thread's tcb.
2466 * Effectively, execve thread's tcb replaces leader's tcb.
2467 *
2468 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2469 * on exit syscall) in multithreaded programs exactly
2470 * in order to handle this case.
2471 *
2472 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2473 * On 2.6 and earlier, it can return garbage.
2474 */
2475 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2476 long old_pid = 0;
2477 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2478 && old_pid > 0
2479 && old_pid != pid
2480 ) {
2481 struct tcb *execve_thread = pid2tcb(old_pid);
2482 if (tcp) {
2483 outf = tcp->outf;
2484 curcol = tcp->curcol;
2485 if (!cflag) {
2486 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) {
2487 /* We printed "syscall(some params"
2488 * but didn't print "\n" yet.
2489 */
2490 tprints(" <unfinished ...>\n");
2491 }
2492 printleader(tcp);
2493 tprintf("+++ superseded by execve in pid %lu +++", old_pid);
2494 printtrailer();
2495 fflush(outf);
2496 }
2497 if (execve_thread) {
2498 /* swap output FILEs (needed for -ff) */
2499 tcp->outf = execve_thread->outf;
2500 execve_thread->outf = outf;
2501 }
2502 droptcb(tcp);
2503 }
2504 tcp = execve_thread;
2505 if (tcp) {
2506 tcp->pid = pid;
2507 tcp->flags |= TCB_REPRINT;
2508 }
2509 }
2510 }
2511#endif
2512
Denys Vlasenko5d645812011-08-20 12:48:18 +02002513 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002514#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002515 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002516 /* This is needed to go with the CLONE_PTRACE
2517 changes in process.c/util.c: we might see
2518 the child's initial trap before we see the
2519 parent return from the clone syscall.
2520 Leave the child suspended until the parent
2521 returns from its system call. Only then
2522 will we have the association of parent and
2523 child so that we know how to do clearbpt
2524 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002525 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002526 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002527 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002528 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002529 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002530 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002531 else
2532 /* This can happen if a clone call used
2533 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002534#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002535 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002536 if (WIFSTOPPED(status))
2537 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002538 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002539 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002541 /* set current output file */
2542 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002543 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002544#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002545 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002546 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2547 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002549#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002550
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002552 if (pid == strace_child)
2553 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002554 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002555 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2556 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002557#ifdef WCOREDUMP
Roland McGrath2efe8792004-01-13 09:59:45 +00002558 tprintf("+++ killed by %s %s+++",
2559 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002560 WCOREDUMP(status) ? "(core dumped) " : "");
2561#else
2562 tprintf("+++ killed by %s +++",
2563 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002564#endif
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002565 printtrailer();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002567 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568 droptcb(tcp);
2569 continue;
2570 }
2571 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002572 if (pid == strace_child)
2573 exit_code = WEXITSTATUS(status);
Roland McGrath0a396902003-06-10 03:05:53 +00002574 if (tcp == tcp_last) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +00002575 if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
Roland McGrath0a396902003-06-10 03:05:53 +00002576 tprintf(" <unfinished ... exit status %d>\n",
2577 WEXITSTATUS(status));
2578 tcp_last = NULL;
2579 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002580 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2581 printleader(tcp);
2582 tprintf("+++ exited with %d +++", WEXITSTATUS(status));
2583 printtrailer();
2584 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002585 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002586 droptcb(tcp);
2587 continue;
2588 }
2589 if (!WIFSTOPPED(status)) {
2590 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2591 droptcb(tcp);
2592 continue;
2593 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002594
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002595 /* Is this the very first time we see this tracee stopped? */
2596 if (tcp->flags & TCB_STARTUP) {
2597 if (debug)
2598 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002599 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002600 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002601 /*
2602 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002603 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002604 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002605 if (clearbpt(tcp) < 0) {
2606 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002607 droptcb(tcp);
2608 cleanup();
2609 return -1;
2610 }
2611 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002612#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002613 if (ptrace_setoptions) {
2614 if (debug)
2615 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2616 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2617 if (errno != ESRCH) {
2618 /* Should never happen, really */
2619 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002620 }
2621 }
2622 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002623#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002624 }
2625
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002626 if (event != 0) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002627 /* Ptrace event (we ignore all of them for now) */
2628 goto restart_tracee_with_sig_0;
2629 }
2630
2631 sig = WSTOPSIG(status);
2632
2633 /* Is this post-attach SIGSTOP?
2634 * Interestingly, the process may stop
2635 * with STOPSIG equal to some other signal
2636 * than SIGSTOP if we happend to attach
2637 * just before the process takes a signal.
2638 */
2639 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2640 if (debug)
2641 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2642 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002643 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002644 }
2645
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002646 if (sig != syscall_trap_sig) {
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002647 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002648 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002649 siginfo_t si;
2650#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002651 long pc = 0;
2652 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002653
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002654 upeek(tcp, PT_CR_IPSR, &psr);
2655 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002656
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002657# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002658 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002659# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002660# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002661#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002662# define PC_FORMAT_STR ""
2663# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002664#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002665 printleader(tcp);
Dmitry V. Levin436d8922011-11-29 00:15:59 +00002666 if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002667 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002668 printsiginfo(&si, verbose(tcp));
2669 tprintf(" (%s)" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002670 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002671 PC_FORMAT_ARG);
2672 } else
2673 tprintf("--- %s by %s" PC_FORMAT_STR " ---",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002674 strsignal(sig),
2675 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002676 PC_FORMAT_ARG);
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002677 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002678 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002679 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002680 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002681 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002682
2683 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002684 if (interrupted)
2685 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002686
2687 /* This should be syscall entry or exit.
2688 * (Or it still can be that pesky post-execve SIGTRAP!)
2689 * Handle it.
2690 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002691 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2692 /* ptrace() failed in trace_syscall() with ESRCH.
2693 * Likely a result of process disappearing mid-flight.
2694 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002695 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002696 */
2697 if (tcp->flags & TCB_ATTACHED) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002698 if (tcp_last) {
2699 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002700 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002701 */
2702 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002703 tprints(" <unfinished ...>");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002704 printtrailer();
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002705 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002706 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002707 /* We assume that ptrace error was caused by process death.
2708 * We used to detach(tcp) here, but since we no longer
2709 * implement "detach before death" policy/hack,
2710 * we can let this process to report its death to us
2711 * normally, via WIFEXITED or WIFSIGNALED wait status.
2712 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002713 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002714 /* It's our real child (and we also trace it) */
2715 /* my_tkill(pid, SIGKILL); - why? */
2716 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002717 }
2718 continue;
2719 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002720 restart_tracee_with_sig_0:
2721 sig = 0;
2722 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002723 /* Remember current print column before continuing. */
2724 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002725 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002726 cleanup();
2727 return -1;
2728 }
2729 }
2730 return 0;
2731}
2732
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002733#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002734
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002735void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002736tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002737{
2738 va_list args;
2739
Andreas Schwabe5355de2009-10-27 16:56:43 +01002740 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002741 if (outf) {
2742 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002743 if (n < 0) {
2744 if (outf != stderr)
2745 perror(outfname == NULL
2746 ? "<writing to pipe>" : outfname);
2747 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002748 curcol += n;
2749 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002750 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002751}
2752
2753void
2754tprints(const char *str)
2755{
2756 if (outf) {
2757 int n = fputs(str, outf);
2758 if (n >= 0) {
2759 curcol += strlen(str);
2760 return;
2761 }
2762 if (outf != stderr)
2763 perror(outfname == NULL
2764 ? "<writing to pipe>" : outfname);
2765 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002766}
2767
2768void
Denys Vlasenko12014262011-05-30 14:00:14 +02002769printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002770{
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002771 if (tcp_last) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002772 if (tcp_last->ptrace_errno) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002773 if (tcp_last->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002774 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002775 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002776 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002777 tprints("= ? <unavailable>\n");
Roland McGratheb9e2e82009-06-02 16:49:22 -07002778 tcp_last->ptrace_errno = 0;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002779 } else if (!outfname || followfork < 2 || tcp_last == tcp) {
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002780 tcp_last->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002781 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002782 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002783 }
2784 curcol = 0;
2785 if ((followfork == 1 || pflag_seen > 1) && outfname)
2786 tprintf("%-5d ", tcp->pid);
2787 else if (nprocs > 1 && !outfname)
2788 tprintf("[pid %5u] ", tcp->pid);
2789 if (tflag) {
2790 char str[sizeof("HH:MM:SS")];
2791 struct timeval tv, dtv;
2792 static struct timeval otv;
2793
2794 gettimeofday(&tv, NULL);
2795 if (rflag) {
2796 if (otv.tv_sec == 0)
2797 otv = tv;
2798 tv_sub(&dtv, &tv, &otv);
2799 tprintf("%6ld.%06ld ",
2800 (long) dtv.tv_sec, (long) dtv.tv_usec);
2801 otv = tv;
2802 }
2803 else if (tflag > 2) {
2804 tprintf("%ld.%06ld ",
2805 (long) tv.tv_sec, (long) tv.tv_usec);
2806 }
2807 else {
2808 time_t local = tv.tv_sec;
2809 strftime(str, sizeof(str), "%T", localtime(&local));
2810 if (tflag > 1)
2811 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2812 else
2813 tprintf("%s ", str);
2814 }
2815 }
2816 if (iflag)
2817 printcall(tcp);
2818}
2819
2820void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002821tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002822{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002823 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002824 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002825}
2826
2827void
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002828printtrailer(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002829{
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002830 tprints("\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002831 tcp_last = NULL;
2832}
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002833
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002834#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002835
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002836int
2837mp_ioctl(int fd, int cmd, void *arg, int size)
2838{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002839 struct iovec iov[2];
2840 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002841
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002842 iov[0].iov_base = &cmd;
2843 iov[0].iov_len = sizeof cmd;
2844 if (arg) {
2845 ++n;
2846 iov[1].iov_base = arg;
2847 iov[1].iov_len = size;
2848 }
Roland McGrath553a6092002-12-16 20:40:39 +00002849
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002850 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002851}
2852
2853#endif