blob: 20a32b3c0fdf06399f4d0771bea0cbebde91a101 [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
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100106#ifdef USE_SEIZE
107static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
108# define use_seize (post_attach_sigstop == 0)
109#else
110# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
111# define use_seize 0
112#endif
113
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000114/* Sometimes we want to print only succeeding syscalls. */
115int not_failing_only = 0;
116
Grant Edwards8a082772011-04-07 20:25:40 +0000117/* Show path associated with fd arguments */
118int show_fd_path = 0;
119
120/* are we filtering traces based on paths? */
121int tracing_paths = 0;
122
Dmitry V. Levina6809652008-11-10 17:14:58 +0000123static int exit_code = 0;
124static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200125static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700126
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000127static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200128static uid_t run_uid;
129static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200132static int acolumn = DEFAULT_ACOLUMN;
133static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000134static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200135static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100136struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100137static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200138static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200139static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200140static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100142static char *os_release; /* from uname() */
143
Denys Vlasenko4c196382012-01-04 15:11:09 +0100144static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100145static int trace(void);
146static void cleanup(void);
147static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148static sigset_t empty_set, blocked_set;
149
150#ifdef HAVE_SIG_ATOMIC_T
151static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100152#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100154#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000156#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
Andreas Schwabe5355de2009-10-27 16:56:43 +0100158static struct tcb *pfd2tcb(int pfd);
159static void reaper(int sig);
160static void rebuild_pollv(void);
Roland McGrathee9d4352002-12-18 04:16:10 +0000161static struct pollfd *pollv;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163#ifndef HAVE_POLLABLE_PROCFS
164
Andreas Schwabe5355de2009-10-27 16:56:43 +0100165static void proc_poll_open(void);
166static void proc_poller(int pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167
168struct proc_pollfd {
169 int fd;
170 int revents;
171 int pid;
172};
173
174static int poller_pid;
175static int proc_poll_pipe[2] = { -1, -1 };
176
177#endif /* !HAVE_POLLABLE_PROCFS */
178
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000179#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000180#define POLLWANT POLLWRNORM
181#else
182#define POLLWANT POLLPRI
183#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000184#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185
186static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200187usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188{
189 fprintf(ofp, "\
Grant Edwards8a082772011-04-07 20:25:40 +0000190usage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000191 [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000192 [-P path] [command [arg ...]]\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200193 or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000194 [command [arg ...]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200196-C -- like -c but also print regular output while processes are running\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197-f -- follow forks, -ff -- with output into separate files\n\
198-F -- attempt to follow vforks, -h -- print help message\n\
199-i -- print instruction pointer at time of syscall\n\
200-q -- suppress messages about attaching, detaching, etc.\n\
201-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
202-T -- print time spent in each syscall, -V -- print version\n\
203-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
204-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000205-y -- print paths associated with file descriptor arguments\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206-a column -- alignment COLUMN for printing syscall results (default %d)\n\
207-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
208 options: trace, abbrev, verbose, raw, signal, read, or write\n\
209-o file -- send trace output to FILE instead of stderr\n\
210-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
211-p pid -- trace process with process id PID, may be repeated\n\
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000212-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
214-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
215-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000216-E var=val -- put var=val in the environment for command\n\
217-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000218-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000219" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000220-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000221 */
222, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 exit(exitval);
224}
225
Denys Vlasenko75422762011-05-27 14:36:01 +0200226static void die(void) __attribute__ ((noreturn));
227static void die(void)
228{
229 if (strace_tracer_pid == getpid()) {
230 cflag = 0;
231 cleanup();
232 }
233 exit(1);
234}
235
236static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200237{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100238 char *msg;
239
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000240 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100241
242 /* We want to print entire message with single fprintf to ensure
243 * message integrity if stderr is shared with other programs.
244 * Thus we use vasprintf + single fprintf.
245 */
246 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100247 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100248 if (err_no)
249 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
250 else
251 fprintf(stderr, "%s: %s\n", progname, msg);
252 free(msg);
253 } else {
254 /* malloc in vasprintf failed, try it without malloc */
255 fprintf(stderr, "%s: ", progname);
256 vfprintf(stderr, fmt, p);
257 if (err_no)
258 fprintf(stderr, ": %s\n", strerror(err_no));
259 else
260 putc('\n', stderr);
261 }
262 /* We don't switch stderr to buffered, thus fprintf(stderr)
263 * always flushes its output and this is not necessary: */
264 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200265}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200266
Denys Vlasenko75422762011-05-27 14:36:01 +0200267void error_msg(const char *fmt, ...)
268{
269 va_list p;
270 va_start(p, fmt);
271 verror_msg(0, fmt, p);
272 va_end(p);
273}
274
275void error_msg_and_die(const char *fmt, ...)
276{
277 va_list p;
278 va_start(p, fmt);
279 verror_msg(0, fmt, p);
280 die();
281}
282
283void perror_msg(const char *fmt, ...)
284{
285 va_list p;
286 va_start(p, fmt);
287 verror_msg(errno, fmt, p);
288 va_end(p);
289}
290
291void perror_msg_and_die(const char *fmt, ...)
292{
293 va_list p;
294 va_start(p, fmt);
295 verror_msg(errno, fmt, p);
296 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200297}
298
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200299void die_out_of_memory(void)
300{
301 static bool recursed = 0;
302 if (recursed)
303 exit(1);
304 recursed = 1;
305 error_msg_and_die("Out of memory");
306}
307
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308#ifdef SVR4
309#ifdef MIPS
310void
311foobar()
312{
313}
314#endif /* MIPS */
315#endif /* SVR4 */
316
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400317/* Glue for systems without a MMU that cannot provide fork() */
318#ifdef HAVE_FORK
319# define strace_vforked 0
320#else
321# define strace_vforked 1
322# define fork() vfork()
323#endif
324
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100325#ifdef USE_SEIZE
326static int
327ptrace_attach_or_seize(int pid)
328{
329 int r;
330 if (!use_seize)
331 return ptrace(PTRACE_ATTACH, pid, 0, 0);
332 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
333 if (r)
334 return r;
335 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
336 return r;
337}
338#else
339# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
340#endif
341
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200342static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000343set_cloexec_flag(int fd)
344{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200345 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000346
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200347 flags = fcntl(fd, F_GETFD);
348 if (flags < 0) {
349 /* Can happen only if fd is bad.
350 * Should never happen: if it does, we have a bug
351 * in the caller. Therefore we just abort
352 * instead of propagating the error.
353 */
354 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000355 }
356
357 newflags = flags | FD_CLOEXEC;
358 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200359 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200361 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362}
363
364/*
365 * When strace is setuid executable, we have to swap uids
366 * before and after filesystem and process management operations.
367 */
368static void
369swap_uid(void)
370{
371#ifndef SVR4
372 int euid = geteuid(), uid = getuid();
373
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200374 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200375 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000376 }
377#endif
378}
379
Roland McGrath4bfa6262007-07-05 20:03:16 +0000380#if _LFS64_LARGEFILE
381# define fopen_for_output fopen64
382#else
383# define fopen_for_output fopen
384#endif
385
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000386static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200387strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000388{
389 FILE *fp;
390
391 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200392 fp = fopen_for_output(path, "w");
393 if (!fp)
394 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000395 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200396 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000397 return fp;
398}
399
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200400static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000401
402#ifndef _PATH_BSHELL
403# define _PATH_BSHELL "/bin/sh"
404#endif
405
406/*
407 * We cannot use standard popen(3) here because we have to distinguish
408 * popen child process from other processes we trace, and standard popen(3)
409 * does not export its child's pid.
410 */
411static FILE *
412strace_popen(const char *command)
413{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200414 FILE *fp;
415 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000416
417 swap_uid();
418 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200419 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200421 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000422
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200423 popen_pid = vfork();
424 if (popen_pid == -1)
425 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000426
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200427 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000428 /* child */
429 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200430 if (fds[0] != 0) {
431 if (dup2(fds[0], 0))
432 perror_msg_and_die("dup2");
433 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000434 }
435 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200436 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000437 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200438
439 /* parent */
440 close(fds[0]);
441 swap_uid();
442 fp = fdopen(fds[1], "w");
443 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200444 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200445 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000446}
447
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200448static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000449newoutf(struct tcb *tcp)
450{
451 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000452 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000453 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200454 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000455 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000456}
457
Roland McGrath02203312007-06-11 22:06:31 +0000458static void
459startup_attach(void)
460{
461 int tcbi;
462 struct tcb *tcp;
463
464 /*
465 * Block user interruptions as we would leave the traced
466 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200467 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200468 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000469 */
470 if (interactive)
471 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
472
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000473 if (daemonized_tracer) {
474 pid_t pid = fork();
475 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200476 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000477 }
478 if (pid) { /* parent */
479 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200480 * Wait for grandchild to attach to straced process
481 * (grandparent). Grandchild SIGKILLs us after it attached.
482 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000483 * it proceeds to exec the straced program.
484 */
485 pause();
486 _exit(0); /* paranoia */
487 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200488 /* grandchild */
489 /* We will be the tracer process. Remember our new pid: */
490 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000491 }
492
Roland McGrath02203312007-06-11 22:06:31 +0000493 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
494 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200495
Denys Vlasenkod116a732011-09-05 14:01:33 +0200496 /* Is this a process we should attach to, but not yet attached? */
497 if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
498 continue; /* no */
499
500 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000501 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200502 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000503
504#ifdef USE_PROCFS
505 if (proc_open(tcp, 1) < 0) {
506 fprintf(stderr, "trouble opening proc file\n");
507 droptcb(tcp);
508 continue;
509 }
510#else /* !USE_PROCFS */
511# ifdef LINUX
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000512 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000513 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000514 DIR *dir;
515
516 sprintf(procdir, "/proc/%d/task", tcp->pid);
517 dir = opendir(procdir);
518 if (dir != NULL) {
519 unsigned int ntid = 0, nerr = 0;
520 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200521
Roland McGrath02203312007-06-11 22:06:31 +0000522 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200523 struct tcb *cur_tcp;
524 int tid;
525
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000526 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000527 continue;
528 tid = atoi(de->d_name);
529 if (tid <= 0)
530 continue;
531 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100532 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000533 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200534 if (debug)
535 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200536 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200537 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200538 if (debug)
539 fprintf(stderr, "attach to pid %d succeeded\n", tid);
540 cur_tcp = tcp;
541 if (tid != tcp->pid)
542 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100543 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000544 }
545 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200546 if (interactive) {
547 sigprocmask(SIG_SETMASK, &empty_set, NULL);
548 if (interrupted)
549 goto ret;
550 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
551 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000552 ntid -= nerr;
553 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000554 perror("attach: ptrace(PTRACE_ATTACH, ...)");
555 droptcb(tcp);
556 continue;
557 }
558 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000559 fprintf(stderr, ntid > 1
560? "Process %u attached with %u threads - interrupt to quit\n"
561: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200562 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000563 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200564 if (!(tcp->flags & TCB_STARTUP)) {
565 /* -p PID, we failed to attach to PID itself
566 * but did attach to some of its sibling threads.
567 * Drop PID's tcp.
568 */
569 droptcb(tcp);
570 }
Roland McGrath02203312007-06-11 22:06:31 +0000571 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000572 } /* if (opendir worked) */
573 } /* if (-f) */
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200574# endif /* LINUX */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100575 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000576 perror("attach: ptrace(PTRACE_ATTACH, ...)");
577 droptcb(tcp);
578 continue;
579 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100580 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200581 if (debug)
582 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000583
584 if (daemonized_tracer) {
585 /*
586 * It is our grandparent we trace, not a -p PID.
587 * Don't want to just detach on exit, so...
588 */
589 tcp->flags &= ~TCB_ATTACHED;
590 /*
591 * Make parent go away.
592 * Also makes grandparent's wait() unblock.
593 */
594 kill(getppid(), SIGKILL);
595 }
596
Roland McGrath02203312007-06-11 22:06:31 +0000597#endif /* !USE_PROCFS */
598 if (!qflag)
599 fprintf(stderr,
600 "Process %u attached - interrupt to quit\n",
601 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200602 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000603
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200604 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000605 if (interactive)
606 sigprocmask(SIG_SETMASK, &empty_set, NULL);
607}
608
609static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200610startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000611{
612 struct stat statbuf;
613 const char *filename;
614 char pathname[MAXPATHLEN];
615 int pid = 0;
616 struct tcb *tcp;
617
618 filename = argv[0];
619 if (strchr(filename, '/')) {
620 if (strlen(filename) > sizeof pathname - 1) {
621 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200622 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000623 }
624 strcpy(pathname, filename);
625 }
626#ifdef USE_DEBUGGING_EXEC
627 /*
628 * Debuggers customarily check the current directory
629 * first regardless of the path but doing that gives
630 * security geeks a panic attack.
631 */
632 else if (stat(filename, &statbuf) == 0)
633 strcpy(pathname, filename);
634#endif /* USE_DEBUGGING_EXEC */
635 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000636 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000637 int m, n, len;
638
639 for (path = getenv("PATH"); path && *path; path += m) {
640 if (strchr(path, ':')) {
641 n = strchr(path, ':') - path;
642 m = n + 1;
643 }
644 else
645 m = n = strlen(path);
646 if (n == 0) {
647 if (!getcwd(pathname, MAXPATHLEN))
648 continue;
649 len = strlen(pathname);
650 }
651 else if (n > sizeof pathname - 1)
652 continue;
653 else {
654 strncpy(pathname, path, n);
655 len = n;
656 }
657 if (len && pathname[len - 1] != '/')
658 pathname[len++] = '/';
659 strcpy(pathname + len, filename);
660 if (stat(pathname, &statbuf) == 0 &&
661 /* Accept only regular files
662 with some execute bits set.
663 XXX not perfect, might still fail */
664 S_ISREG(statbuf.st_mode) &&
665 (statbuf.st_mode & 0111))
666 break;
667 }
668 }
669 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200670 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000671 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000672 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000673 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200674 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000675 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200676 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
677 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678 ) {
679 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200680 if (outf != stderr)
681 close(fileno(outf));
Roland McGrath02203312007-06-11 22:06:31 +0000682#ifdef USE_PROCFS
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200683# ifdef MIPS
Roland McGrath02203312007-06-11 22:06:31 +0000684 /* Kludge for SGI, see proc_open for details. */
685 sa.sa_handler = foobar;
686 sa.sa_flags = 0;
687 sigemptyset(&sa.sa_mask);
688 sigaction(SIGINT, &sa, NULL);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200689# endif
690# ifndef FREEBSD
Roland McGrath02203312007-06-11 22:06:31 +0000691 pause();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200692# else
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200693 kill(pid, SIGSTOP);
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200694# endif
Roland McGrath02203312007-06-11 22:06:31 +0000695#else /* !USE_PROCFS */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100696 if (!daemonized_tracer && !use_seize) {
697 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200698 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000699 }
Roland McGrath02203312007-06-11 22:06:31 +0000700 }
Roland McGrath02203312007-06-11 22:06:31 +0000701
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200702 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000703 uid_t run_euid = run_uid;
704 gid_t run_egid = run_gid;
705
706 if (statbuf.st_mode & S_ISUID)
707 run_euid = statbuf.st_uid;
708 if (statbuf.st_mode & S_ISGID)
709 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000710 /*
711 * It is important to set groups before we
712 * lose privileges on setuid.
713 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200714 if (initgroups(username, run_gid) < 0) {
715 perror_msg_and_die("initgroups");
716 }
717 if (setregid(run_gid, run_egid) < 0) {
718 perror_msg_and_die("setregid");
719 }
720 if (setreuid(run_uid, run_euid) < 0) {
721 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000722 }
723 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200724 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000725 setreuid(run_uid, run_uid);
726
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000727 if (!daemonized_tracer) {
728 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200729 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000730 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200731 * the immediately following execve syscall.
732 * Can't do this on NOMMU systems, we are after
733 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000734 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400735 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200736 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000737 } else {
738 struct sigaction sv_sigchld;
739 sigaction(SIGCHLD, NULL, &sv_sigchld);
740 /*
741 * Make sure it is not SIG_IGN, otherwise wait
742 * will not block.
743 */
744 signal(SIGCHLD, SIG_DFL);
745 /*
746 * Wait for grandchild to attach to us.
747 * It kills child after that, and wait() unblocks.
748 */
749 alarm(3);
750 wait(NULL);
751 alarm(0);
752 sigaction(SIGCHLD, &sv_sigchld, NULL);
753 }
Roland McGrath02203312007-06-11 22:06:31 +0000754#endif /* !USE_PROCFS */
755
756 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200757 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000758 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000759
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200760 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200761
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200762 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100763 if (!use_seize) {
764 /* child did PTRACE_TRACEME, nothing to do in parent */
765 } else {
766 if (!strace_vforked) {
767 /* Wait until child stopped itself */
768 int status;
769 while (waitpid(pid, &status, WSTOPPED) < 0) {
770 if (errno == EINTR)
771 continue;
772 perror_msg_and_die("waitpid");
773 }
774 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
775 kill(pid, SIGKILL);
776 perror_msg_and_die("Unexpected wait status %x", status);
777 }
778 }
779 /* Else: vforked case, we have no way to sync.
780 * Just attach to it as soon as possible.
781 * This means that we may miss a few first syscalls...
782 */
783
784 if (ptrace_attach_or_seize(pid)) {
785 kill(pid, SIGKILL);
786 perror_msg_and_die("Can't attach to %d", pid);
787 }
788 if (!strace_vforked)
789 kill(pid, SIGCONT);
790 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200791 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200792 if (!strace_vforked)
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100793 tcp->flags |= TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200794 else
795 tcp->flags |= TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200796 }
797 else {
798 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
799 strace_tracer_pid = getpid();
800 /* The tracee is our parent: */
801 pid = getppid();
802 tcp = alloctcb(pid);
803 /* We want subsequent startup_attach() to attach to it: */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000804 tcp->flags |= TCB_ATTACHED;
805 }
Roland McGrath02203312007-06-11 22:06:31 +0000806#ifdef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000807 if (proc_open(tcp, 0) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200808 perror_msg_and_die("trouble opening proc file");
Roland McGrath02203312007-06-11 22:06:31 +0000809 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200810#endif
Roland McGrath02203312007-06-11 22:06:31 +0000811}
812
Wang Chaob13c0de2010-11-12 17:25:19 +0800813#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000814static void kill_save_errno(pid_t pid, int sig)
815{
816 int saved_errno = errno;
817
818 (void) kill(pid, sig);
819 errno = saved_errno;
820}
821
Wang Chaob13c0de2010-11-12 17:25:19 +0800822/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000823 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800824 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000825 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800826 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000827static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200828test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800829{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000830 int pid, expected_grandchild = 0, found_grandchild = 0;
831 const unsigned int test_options = PTRACE_O_TRACECLONE |
832 PTRACE_O_TRACEFORK |
833 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800834
Denys Vlasenko5d645812011-08-20 12:48:18 +0200835 pid = fork();
836 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000837 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200838 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000839 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100840 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000841 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
842 __func__);
843 kill(pid, SIGSTOP);
844 if (fork() < 0)
845 perror_msg_and_die("fork");
846 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800847 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000848
849 while (1) {
850 int status, tracee_pid;
851
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000852 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000853 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000854 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000855 if (errno == EINTR)
856 continue;
857 else if (errno == ECHILD)
858 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000859 kill_save_errno(pid, SIGKILL);
860 perror_msg_and_die("%s: unexpected wait result %d",
861 __func__, tracee_pid);
862 }
863 if (WIFEXITED(status)) {
864 if (WEXITSTATUS(status)) {
865 if (tracee_pid != pid)
866 kill_save_errno(pid, SIGKILL);
867 error_msg_and_die("%s: unexpected exit status %u",
868 __func__, WEXITSTATUS(status));
869 }
870 continue;
871 }
872 if (WIFSIGNALED(status)) {
873 if (tracee_pid != pid)
874 kill_save_errno(pid, SIGKILL);
875 error_msg_and_die("%s: unexpected signal %u",
876 __func__, WTERMSIG(status));
877 }
878 if (!WIFSTOPPED(status)) {
879 if (tracee_pid != pid)
880 kill_save_errno(tracee_pid, SIGKILL);
881 kill(pid, SIGKILL);
882 error_msg_and_die("%s: unexpected wait status %x",
883 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000884 }
885 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000886 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000887 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
888 kill_save_errno(tracee_pid, SIGKILL);
889 kill_save_errno(pid, SIGKILL);
890 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800891 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000892 continue;
893 }
894 switch (WSTOPSIG(status)) {
895 case SIGSTOP:
896 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
897 && errno != EINVAL && errno != EIO)
898 perror_msg("PTRACE_SETOPTIONS");
899 break;
900 case SIGTRAP:
901 if (status >> 16 == PTRACE_EVENT_FORK) {
902 long msg = 0;
903
904 if (ptrace(PTRACE_GETEVENTMSG, pid,
905 NULL, (long) &msg) == 0)
906 expected_grandchild = msg;
907 }
908 break;
909 }
910 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
911 kill_save_errno(pid, SIGKILL);
912 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800913 }
914 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000915 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200916 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000917 if (debug)
918 fprintf(stderr, "ptrace_setoptions = %#x\n",
919 ptrace_setoptions);
920 return;
921 }
922 error_msg("Test for PTRACE_O_TRACECLONE failed, "
923 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800924}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200925
926/*
927 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
928 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
929 * and then see whether it will stop with (SIGTRAP | 0x80).
930 *
931 * Use of this option enables correct handling of user-generated SIGTRAPs,
932 * and SIGTRAPs generated by special instructions such as int3 on x86:
933 * _start: .globl _start
934 * int3
935 * movl $42, %ebx
936 * movl $1, %eax
937 * int $0x80
938 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
939 */
940static void
941test_ptrace_setoptions_for_all(void)
942{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000943 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
944 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200945 int pid;
946 int it_worked = 0;
947
948 pid = fork();
949 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200950 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200951
952 if (pid == 0) {
953 pid = getpid();
954 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200955 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000956 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
957 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200958 kill(pid, SIGSTOP);
959 _exit(0); /* parent should see entry into this syscall */
960 }
961
962 while (1) {
963 int status, tracee_pid;
964
965 errno = 0;
966 tracee_pid = wait(&status);
967 if (tracee_pid <= 0) {
968 if (errno == EINTR)
969 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000970 kill_save_errno(pid, SIGKILL);
971 perror_msg_and_die("%s: unexpected wait result %d",
972 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200973 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200974 if (WIFEXITED(status)) {
975 if (WEXITSTATUS(status) == 0)
976 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000977 error_msg_and_die("%s: unexpected exit status %u",
978 __func__, WEXITSTATUS(status));
979 }
980 if (WIFSIGNALED(status)) {
981 error_msg_and_die("%s: unexpected signal %u",
982 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200983 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200984 if (!WIFSTOPPED(status)) {
985 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000986 error_msg_and_die("%s: unexpected wait status %x",
987 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200988 }
989 if (WSTOPSIG(status) == SIGSTOP) {
990 /*
991 * We don't check "options aren't accepted" error.
992 * If it happens, we'll never get (SIGTRAP | 0x80),
993 * and thus will decide to not use the option.
994 * IOW: the outcome of the test will be correct.
995 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000996 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
997 && errno != EINVAL && errno != EIO)
998 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200999 }
1000 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1001 it_worked = 1;
1002 }
1003 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001004 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001005 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001006 }
1007 }
1008
1009 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001010 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001011 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001012 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001013 fprintf(stderr, "ptrace_setoptions = %#x\n",
1014 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001015 return;
1016 }
1017
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001018 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1019 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001020}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001021
1022# ifdef USE_SEIZE
1023static void
1024test_ptrace_seize(void)
1025{
1026 int pid;
1027
1028 pid = fork();
1029 if (pid < 0)
1030 perror_msg_and_die("fork");
1031
1032 if (pid == 0) {
1033 pause();
1034 _exit(0);
1035 }
1036
1037 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1038 * attaching tracee continues to run unless a trap condition occurs.
1039 * PTRACE_SEIZE doesn't affect signal or group stop state.
1040 */
1041 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1042 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1043 } else if (debug) {
1044 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1045 }
1046
1047 kill(pid, SIGKILL);
1048
1049 while (1) {
1050 int status, tracee_pid;
1051
1052 errno = 0;
1053 tracee_pid = waitpid(pid, &status, 0);
1054 if (tracee_pid <= 0) {
1055 if (errno == EINTR)
1056 continue;
1057 perror_msg_and_die("%s: unexpected wait result %d",
1058 __func__, tracee_pid);
1059 }
1060 if (WIFSIGNALED(status)) {
1061 return;
1062 }
1063 error_msg_and_die("%s: unexpected wait status %x",
1064 __func__, status);
1065 }
1066}
1067# else /* !USE_SEIZE */
1068# define test_ptrace_seize() ((void)0)
1069# endif
1070
Wang Chaob13c0de2010-11-12 17:25:19 +08001071#endif
1072
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001073/* Noinline: don't want main to have struct utsname permanently on stack */
1074static void __attribute__ ((noinline))
1075get_os_release(void)
1076{
1077 struct utsname u;
1078 if (uname(&u) < 0)
1079 perror_msg_and_die("uname");
1080 os_release = strdup(u.release);
1081 if (!os_release)
1082 die_out_of_memory();
1083}
1084
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001086main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 struct tcb *tcp;
1089 int c, pid = 0;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001090 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 struct sigaction sa;
1092
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001093 progname = argv[0] ? argv[0] : "strace";
1094
Denys Vlasenko75422762011-05-27 14:36:01 +02001095 strace_tracer_pid = getpid();
1096
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001097 get_os_release();
1098
Roland McGrathee9d4352002-12-18 04:16:10 +00001099 /* Allocate the initial tcbtab. */
1100 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001101 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001102 if (!tcbtab)
1103 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001104 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001105 if (!tcp)
1106 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001107 for (c = 0; c < tcbtabsize; c++)
1108 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001111 set_sortby(DEFAULT_SORTBY);
1112 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 qualify("trace=all");
1114 qualify("abbrev=all");
1115 qualify("verbose=all");
1116 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001118 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001119#ifndef USE_PROCFS
1120 "D"
1121#endif
Grant Edwards8a082772011-04-07 20:25:40 +00001122 "a:e:o:O:p:s:S:u:E:P:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 switch (c) {
1124 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001125 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001126 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001127 }
1128 cflag = CFLAG_ONLY_STATS;
1129 break;
1130 case 'C':
1131 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001132 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001133 }
1134 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 break;
1136 case 'd':
1137 debug++;
1138 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001139#ifndef USE_PROCFS
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001140 case 'D':
1141 daemonized_tracer = 1;
1142 break;
1143#endif
Roland McGrath41c48222008-07-18 00:25:10 +00001144 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001145 optF = 1;
1146 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 case 'f':
1148 followfork++;
1149 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 case 'h':
1151 usage(stdout, 0);
1152 break;
1153 case 'i':
1154 iflag++;
1155 break;
1156 case 'q':
1157 qflag++;
1158 break;
1159 case 'r':
1160 rflag++;
1161 tflag++;
1162 break;
1163 case 't':
1164 tflag++;
1165 break;
1166 case 'T':
1167 dtime++;
1168 break;
1169 case 'x':
1170 xflag++;
1171 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001172 case 'y':
1173 show_fd_path = 1;
1174 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 case 'v':
1176 qualify("abbrev=none");
1177 break;
1178 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001179 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 exit(0);
1181 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001182 case 'z':
1183 not_failing_only = 1;
1184 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 case 'a':
1186 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001187 if (acolumn < 0)
1188 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 break;
1190 case 'e':
1191 qualify(optarg);
1192 break;
1193 case 'o':
1194 outfname = strdup(optarg);
1195 break;
1196 case 'O':
1197 set_overhead(atoi(optarg));
1198 break;
1199 case 'p':
Denys Vlasenko5d645812011-08-20 12:48:18 +02001200 pid = atoi(optarg);
1201 if (pid <= 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001202 error_msg("Invalid process id: '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203 break;
1204 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001205 if (pid == strace_tracer_pid) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001206 error_msg("I'm sorry, I can't let you do that, Dave.");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 break;
1208 }
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001209 tcp = alloc_tcb(pid, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 tcp->flags |= TCB_ATTACHED;
1211 pflag_seen++;
1212 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001213 case 'P':
1214 tracing_paths = 1;
1215 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001216 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001217 }
1218 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219 case 's':
1220 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001221 if (max_strlen < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001222 error_msg_and_die("Invalid -s argument: '%s'", optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001223 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 break;
1225 case 'S':
1226 set_sortby(optarg);
1227 break;
1228 case 'u':
1229 username = strdup(optarg);
1230 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001231 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001232 if (putenv(optarg) < 0)
1233 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001234 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235 default:
1236 usage(stderr, 1);
1237 break;
1238 }
1239 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001240 argv += optind;
1241 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242
Denys Vlasenko102ec492011-08-25 01:27:59 +02001243 acolumn_spaces = malloc(acolumn + 1);
1244 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001245 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001246 memset(acolumn_spaces, ' ', acolumn);
1247 acolumn_spaces[acolumn] = '\0';
1248
Denys Vlasenko837399a2012-01-24 11:37:03 +01001249 /* Must have PROG [ARGS], or -p PID. Not both. */
1250 if (!argv[0] == !pflag_seen)
Roland McGrathce0d1542003-11-11 21:24:23 +00001251 usage(stderr, 1);
1252
Wang Chaod322a4b2010-08-05 14:30:11 +08001253 if (pflag_seen && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001254 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001255 }
1256
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001257 if (!followfork)
1258 followfork = optF;
1259
Roland McGrathcb9def62006-04-25 07:48:03 +00001260 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001261 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001262 }
1263
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001264 /* See if they want to run as another user. */
1265 if (username != NULL) {
1266 struct passwd *pent;
1267
1268 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001269 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001271 pent = getpwnam(username);
1272 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001273 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 }
1275 run_uid = pent->pw_uid;
1276 run_gid = pent->pw_gid;
1277 }
1278 else {
1279 run_uid = getuid();
1280 run_gid = getgid();
1281 }
1282
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001283#ifdef LINUX
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001284 if (followfork)
1285 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001286 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001287 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001288#endif
1289
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001290 /* Check if they want to redirect the output. */
1291 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001292 /* See if they want to pipe the output. */
1293 if (outfname[0] == '|' || outfname[0] == '!') {
1294 /*
1295 * We can't do the <outfname>.PID funny business
1296 * when using popen, so prohibit it.
1297 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001298 if (followfork > 1)
1299 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1300 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001301 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001302 else if (followfork <= 1)
1303 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 }
1305
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001306 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001307 char *buf = malloc(BUFSIZ);
1308 if (!buf)
1309 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001311 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001312 if (outfname && argv[0]) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 interactive = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001315 }
Wang Chaob13c0de2010-11-12 17:25:19 +08001316
Roland McGrath54cc1c82007-11-03 23:34:11 +00001317 /* Valid states here:
Denys Vlasenko837399a2012-01-24 11:37:03 +01001318 argv[0] pflag_seen outfname interactive
1319 yes 0 0 1
1320 no 1 0 1
1321 yes 0 1 0
1322 no 1 1 1
Roland McGrath54cc1c82007-11-03 23:34:11 +00001323 */
1324
1325 /* STARTUP_CHILD must be called before the signal handlers get
1326 installed below as they are inherited into the spawned process.
1327 Also we do not need to be protected by them as during interruption
1328 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001329 if (argv[0])
1330 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332 sigemptyset(&empty_set);
1333 sigemptyset(&blocked_set);
1334 sa.sa_handler = SIG_IGN;
1335 sigemptyset(&sa.sa_mask);
1336 sa.sa_flags = 0;
1337 sigaction(SIGTTOU, &sa, NULL);
1338 sigaction(SIGTTIN, &sa, NULL);
Denys Vlasenko837399a2012-01-24 11:37:03 +01001339 /* In interactive mode (if no -o OUTFILE, or -p PID is used),
1340 * fatal signals are blocked across syscall waits, and acted on
1341 * in between. In non-interactive mode, signals are ignored.
1342 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001343 if (interactive) {
1344 sigaddset(&blocked_set, SIGHUP);
1345 sigaddset(&blocked_set, SIGINT);
1346 sigaddset(&blocked_set, SIGQUIT);
1347 sigaddset(&blocked_set, SIGPIPE);
1348 sigaddset(&blocked_set, SIGTERM);
1349 sa.sa_handler = interrupt;
1350#ifdef SUNOS4
1351 /* POSIX signals on sunos4.1 are a little broken. */
1352 sa.sa_flags = SA_INTERRUPT;
1353#endif /* SUNOS4 */
1354 }
1355 sigaction(SIGHUP, &sa, NULL);
1356 sigaction(SIGINT, &sa, NULL);
1357 sigaction(SIGQUIT, &sa, NULL);
1358 sigaction(SIGPIPE, &sa, NULL);
1359 sigaction(SIGTERM, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001360#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001361 sa.sa_handler = reaper;
1362 sigaction(SIGCHLD, &sa, NULL);
Roland McGrath553a6092002-12-16 20:40:39 +00001363#else
1364 /* Make sure SIGCHLD has the default action so that waitpid
1365 definitely works without losing track of children. The user
1366 should not have given us a bogus state to inherit, but he might
1367 have. Arguably we should detect SIG_IGN here and pass it on
1368 to children, but probably noone really needs that. */
1369 sa.sa_handler = SIG_DFL;
1370 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001371#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001372
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001373 if (pflag_seen || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001374 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001375
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376 if (trace() < 0)
1377 exit(1);
1378 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001379 fflush(NULL);
1380 if (exit_code > 0xff) {
1381 /* Child was killed by a signal, mimic that. */
1382 exit_code &= 0xff;
1383 signal(exit_code, SIG_DFL);
1384 raise(exit_code);
1385 /* Paranoia - what if this signal is not fatal?
1386 Exit with 128 + signo then. */
1387 exit_code += 128;
1388 }
1389 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390}
1391
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001392static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001393expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001394{
1395 /* Allocate some more TCBs and expand the table.
1396 We don't want to relocate the TCBs because our
1397 callers have pointers and it would be a pain.
1398 So tcbtab is a table of pointers. Since we never
1399 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001400 int i = tcbtabsize;
1401 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1402 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001403 if (!newtab || !newtcbs)
1404 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001405 tcbtabsize *= 2;
1406 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001407 while (i < tcbtabsize)
1408 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001409}
1410
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001412alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413{
1414 int i;
1415 struct tcb *tcp;
1416
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001417 if (nprocs == tcbtabsize)
1418 expand_tcbtab();
1419
Roland McGrathee9d4352002-12-18 04:16:10 +00001420 for (i = 0; i < tcbtabsize; i++) {
1421 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001423 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001425 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001427#if SUPPORTED_PERSONALITIES > 1
1428 tcp->currpers = current_personality;
1429#endif
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001430#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001431 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001432#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001434 if (debug)
1435 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001436 if (command_options_parsed)
1437 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 return tcp;
1439 }
1440 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001441 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442}
1443
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001444#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445int
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001446proc_open(struct tcb *tcp, int attaching)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447{
1448 char proc[32];
1449 long arg;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001450#ifdef SVR4
John Hughes19e49982001-10-19 08:59:12 +00001451 int i;
1452 sysset_t syscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453 sigset_t signals;
1454 fltset_t faults;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001455#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456#ifndef HAVE_POLLABLE_PROCFS
1457 static int last_pfd;
1458#endif
1459
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00001460#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001461 /* Open the process pseudo-files in /proc. */
1462 sprintf(proc, "/proc/%d/ctl", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001463 tcp->pfd = open(proc, O_WRONLY|O_EXCL);
1464 if (tcp->pfd < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465 perror("strace: open(\"/proc/...\", ...)");
1466 return -1;
1467 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001468 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001469 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001470 tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
1471 if (tcp->pfd_stat < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001472 perror("strace: open(\"/proc/...\", ...)");
1473 return -1;
1474 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001475 set_cloexec_flag(tcp->pfd_stat);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001476 sprintf(proc, "/proc/%d/as", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001477 tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
1478 if (tcp->pfd_as < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001479 perror("strace: open(\"/proc/...\", ...)");
1480 return -1;
1481 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001482 set_cloexec_flag(tcp->pfd_as);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001483#else
1484 /* Open the process pseudo-file in /proc. */
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001485# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001486 sprintf(proc, "/proc/%d", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001487 tcp->pfd = open(proc, O_RDWR|O_EXCL);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001488# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001489 sprintf(proc, "/proc/%d/mem", tcp->pid);
Andreas Schwab372cc842010-07-09 11:49:27 +02001490 tcp->pfd = open(proc, O_RDWR);
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001491# endif
Andreas Schwab372cc842010-07-09 11:49:27 +02001492 if (tcp->pfd < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001493 perror("strace: open(\"/proc/...\", ...)");
1494 return -1;
1495 }
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02001496 set_cloexec_flag(tcp->pfd);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001497#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001498#ifdef FREEBSD
1499 sprintf(proc, "/proc/%d/regs", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001500 tcp->pfd_reg = open(proc, O_RDONLY);
1501 if (tcp->pfd_reg < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001502 perror("strace: open(\"/proc/.../regs\", ...)");
1503 return -1;
1504 }
1505 if (cflag) {
1506 sprintf(proc, "/proc/%d/status", tcp->pid);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001507 tcp->pfd_status = open(proc, O_RDONLY);
1508 if (tcp->pfd_status < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001509 perror("strace: open(\"/proc/.../status\", ...)");
1510 return -1;
1511 }
1512 } else
1513 tcp->pfd_status = -1;
1514#endif /* FREEBSD */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001515 rebuild_pollv();
1516 if (!attaching) {
1517 /*
1518 * Wait for the child to pause. Because of a race
1519 * condition we have to poll for the event.
1520 */
1521 for (;;) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001522 if (IOCTL_STATUS(tcp) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001523 perror("strace: PIOCSTATUS");
1524 return -1;
1525 }
1526 if (tcp->status.PR_FLAGS & PR_ASLEEP)
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001527 break;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001528 }
1529 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001530#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001531 /* Stop the process so that we own the stop. */
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001532 if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001533 perror("strace: PIOCSTOP");
1534 return -1;
1535 }
Roland McGrath553a6092002-12-16 20:40:39 +00001536#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537#ifdef PIOCSET
1538 /* Set Run-on-Last-Close. */
1539 arg = PR_RLC;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001540 if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 perror("PIOCSET PR_RLC");
1542 return -1;
1543 }
1544 /* Set or Reset Inherit-on-Fork. */
1545 arg = PR_FORK;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001546 if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 perror("PIOC{SET,RESET} PR_FORK");
1548 return -1;
1549 }
1550#else /* !PIOCSET */
Roland McGrath553a6092002-12-16 20:40:39 +00001551#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552 if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
1553 perror("PIOCSRLC");
1554 return -1;
1555 }
1556 if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
1557 perror("PIOC{S,R}FORK");
1558 return -1;
1559 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001560#else /* FREEBSD */
1561 /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1562 if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1563 perror("PIOCGFL");
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001564 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001565 }
1566 arg &= ~PF_LINGER;
1567 if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001568 perror("PIOCSFL");
1569 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001570 }
1571#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572#endif /* !PIOCSET */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001573#ifndef FREEBSD
John Hughes19e49982001-10-19 08:59:12 +00001574 /* Enable all syscall entries we care about. */
1575 premptyset(&syscalls);
1576 for (i = 1; i < MAX_QUALS; ++i) {
1577 if (i > (sizeof syscalls) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001578 if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
John Hughes19e49982001-10-19 08:59:12 +00001579 }
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001580 praddset(&syscalls, SYS_execve);
John Hughes19e49982001-10-19 08:59:12 +00001581 if (followfork) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001582 praddset(&syscalls, SYS_fork);
John Hughes19e49982001-10-19 08:59:12 +00001583#ifdef SYS_forkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001584 praddset(&syscalls, SYS_forkall);
John Hughes19e49982001-10-19 08:59:12 +00001585#endif
Roland McGrath553a6092002-12-16 20:40:39 +00001586#ifdef SYS_fork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001587 praddset(&syscalls, SYS_fork1);
John Hughes19e49982001-10-19 08:59:12 +00001588#endif
1589#ifdef SYS_rfork1
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001590 praddset(&syscalls, SYS_rfork1);
John Hughes19e49982001-10-19 08:59:12 +00001591#endif
1592#ifdef SYS_rforkall
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001593 praddset(&syscalls, SYS_rforkall);
John Hughes19e49982001-10-19 08:59:12 +00001594#endif
1595 }
1596 if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 perror("PIOCSENTRY");
1598 return -1;
1599 }
John Hughes19e49982001-10-19 08:59:12 +00001600 /* Enable the syscall exits. */
1601 if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602 perror("PIOSEXIT");
1603 return -1;
1604 }
John Hughes19e49982001-10-19 08:59:12 +00001605 /* Enable signals we care about. */
1606 premptyset(&signals);
1607 for (i = 1; i < MAX_QUALS; ++i) {
1608 if (i > (sizeof signals) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001609 if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
John Hughes19e49982001-10-19 08:59:12 +00001610 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001611 if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612 perror("PIOCSTRACE");
1613 return -1;
1614 }
John Hughes19e49982001-10-19 08:59:12 +00001615 /* Enable faults we care about */
1616 premptyset(&faults);
1617 for (i = 1; i < MAX_QUALS; ++i) {
1618 if (i > (sizeof faults) * CHAR_BIT) break;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001619 if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
John Hughes19e49982001-10-19 08:59:12 +00001620 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001621 if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 perror("PIOCSFAULT");
1623 return -1;
1624 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001625#else /* FREEBSD */
1626 /* set events flags. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001627 arg = S_SIG | S_SCE | S_SCX;
1628 if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001629 perror("PIOCBIS");
1630 return -1;
1631 }
1632#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 if (!attaching) {
1634#ifdef MIPS
1635 /*
1636 * The SGI PRSABORT doesn't work for pause() so
1637 * we send it a caught signal to wake it up.
1638 */
1639 kill(tcp->pid, SIGINT);
1640#else /* !MIPS */
Roland McGrath553a6092002-12-16 20:40:39 +00001641#ifdef PRSABORT
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 /* The child is in a pause(), abort it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001643 arg = PRSABORT;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001644 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 perror("PIOCRUN");
1646 return -1;
1647 }
Roland McGrath553a6092002-12-16 20:40:39 +00001648#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001649#endif /* !MIPS*/
1650#ifdef FREEBSD
1651 /* wake up the child if it received the SIGSTOP */
1652 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001653#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 for (;;) {
1655 /* Wait for the child to do something. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001656 if (IOCTL_WSTOP(tcp) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657 perror("PIOCWSTOP");
1658 return -1;
1659 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001660 if (tcp->status.PR_WHY == PR_SYSENTRY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001661 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko06602d92011-08-24 17:53:52 +02001662 get_scno(tcp);
Roland McGrath76989d72005-06-07 23:21:31 +00001663 if (known_scno(tcp) == SYS_execve)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664 break;
1665 }
1666 /* Set it running: maybe execve will be next. */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001667#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001668 arg = 0;
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001669 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
1670#else
1671 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
1672#endif
1673 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 perror("PIOCRUN");
1675 return -1;
1676 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001677#ifdef FREEBSD
1678 /* handle the case where we "opened" the child before
1679 it did the kill -STOP */
1680 if (tcp->status.PR_WHY == PR_SIGNALLED &&
1681 tcp->status.PR_WHAT == SIGSTOP)
1682 kill(tcp->pid, SIGCONT);
Roland McGrath553a6092002-12-16 20:40:39 +00001683#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 }
1685 }
Denys Vlasenko0890c8a2011-08-21 00:10:45 +02001686#ifdef FREEBSD
1687 else {
Roland McGrath553a6092002-12-16 20:40:39 +00001688 if (attaching < 2) {
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001689 /* We are attaching to an already running process.
1690 * Try to figure out the state of the process in syscalls,
1691 * to handle the first event well.
1692 * This is done by having a look at the "wchan" property of the
1693 * process, which tells where it is stopped (if it is). */
1694 FILE * status;
1695 char wchan[20]; /* should be enough */
Roland McGrath553a6092002-12-16 20:40:39 +00001696
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00001697 sprintf(proc, "/proc/%d/status", tcp->pid);
1698 status = fopen(proc, "r");
1699 if (status &&
1700 (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
1701 "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
1702 strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
1703 strcmp(wchan, "stopevent")) {
1704 /* The process is asleep in the middle of a syscall.
1705 Fake the syscall entry event */
1706 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
1707 tcp->status.PR_WHY = PR_SYSENTRY;
1708 trace_syscall(tcp);
1709 }
1710 if (status)
1711 fclose(status);
1712 } /* otherwise it's a fork being followed */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001713 }
1714#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715#ifndef HAVE_POLLABLE_PROCFS
1716 if (proc_poll_pipe[0] != -1)
1717 proc_poller(tcp->pfd);
1718 else if (nprocs > 1) {
1719 proc_poll_open();
1720 proc_poller(last_pfd);
1721 proc_poller(tcp->pfd);
1722 }
1723 last_pfd = tcp->pfd;
1724#endif /* !HAVE_POLLABLE_PROCFS */
1725 return 0;
1726}
1727
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001728#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001730static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001731pid2tcb(int pid)
1732{
1733 int i;
1734
1735 if (pid <= 0)
1736 return NULL;
1737
1738 for (i = 0; i < tcbtabsize; i++) {
1739 struct tcb *tcp = tcbtab[i];
1740 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1741 return tcp;
1742 }
1743
1744 return NULL;
1745}
1746
1747#ifdef USE_PROCFS
1748
1749static struct tcb *
1750first_used_tcb(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751{
1752 int i;
1753 struct tcb *tcp;
Roland McGrathee9d4352002-12-18 04:16:10 +00001754 for (i = 0; i < tcbtabsize; i++) {
1755 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756 if (tcp->flags & TCB_INUSE)
1757 return tcp;
1758 }
1759 return NULL;
1760}
1761
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762static struct tcb *
Denys Vlasenko12014262011-05-30 14:00:14 +02001763pfd2tcb(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764{
1765 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766
Roland McGrathca16be82003-01-10 19:55:28 +00001767 for (i = 0; i < tcbtabsize; i++) {
1768 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769 if (tcp->pfd != pfd)
1770 continue;
1771 if (tcp->flags & TCB_INUSE)
1772 return tcp;
1773 }
1774 return NULL;
1775}
1776
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001777#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778
1779void
Denys Vlasenko12014262011-05-30 14:00:14 +02001780droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781{
1782 if (tcp->pid == 0)
1783 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001784
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001786 if (debug)
1787 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001788
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001789#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 if (tcp->pfd != -1) {
1791 close(tcp->pfd);
1792 tcp->pfd = -1;
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001793# ifdef FREEBSD
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001794 if (tcp->pfd_reg != -1) {
1795 close(tcp->pfd_reg);
1796 tcp->pfd_reg = -1;
1797 }
1798 if (tcp->pfd_status != -1) {
1799 close(tcp->pfd_status);
1800 tcp->pfd_status = -1;
1801 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001802# endif
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001803 tcp->flags = 0; /* rebuild_pollv needs it */
1804 rebuild_pollv();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 }
Denys Vlasenko8dc0c8c2011-08-20 13:44:56 +02001806#endif
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001807
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001808 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001809 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001810
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001811 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812}
1813
Roland McGrath0a463882007-07-05 18:43:16 +00001814/* detach traced process; continue with sig
1815 Never call DETACH twice on the same process as both unattached and
1816 attached-unstopped processes give the same ESRCH. For unattached process we
1817 would SIGSTOP it and wait for its SIGSTOP notification forever. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818
1819static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001820detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821{
1822 int error = 0;
Roland McGrathca16be82003-01-10 19:55:28 +00001823#ifdef LINUX
Roland McGrath1bfd3102007-08-03 10:02:00 +00001824 int status, catch_sigstop;
Roland McGrathca16be82003-01-10 19:55:28 +00001825#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826
1827 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001828 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829
1830#ifdef LINUX
1831 /*
1832 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001833 * before detaching. Arghh. We go through hoops
1834 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001835 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001836#if defined(SPARC)
1837#undef PTRACE_DETACH
1838#define PTRACE_DETACH PTRACE_SUNDETACH
1839#endif
Roland McGrath02203312007-06-11 22:06:31 +00001840 /*
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001841 * We attached but possibly didn't see the expected SIGSTOP.
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001842 * We must catch exactly one as otherwise the detached process
1843 * would be left stopped (process state T).
Roland McGrath02203312007-06-11 22:06:31 +00001844 */
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001845 catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
Denys Vlasenko4c196382012-01-04 15:11:09 +01001846 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
Denys Vlasenko5d645812011-08-20 12:48:18 +02001847 if (error == 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001848 /* On a clear day, you can see forever. */
Roland McGrath7bf10472002-12-16 20:42:50 +00001849 }
1850 else if (errno != ESRCH) {
1851 /* Shouldn't happen. */
1852 perror("detach: ptrace(PTRACE_DETACH, ...)");
1853 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001854 else if (my_tkill(tcp->pid, 0) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001855 if (errno != ESRCH)
1856 perror("detach: checking sanity");
1857 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001858 else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
Roland McGrath7bf10472002-12-16 20:42:50 +00001859 if (errno != ESRCH)
1860 perror("detach: stopping child");
1861 }
Roland McGrath02203312007-06-11 22:06:31 +00001862 else
1863 catch_sigstop = 1;
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001864 if (catch_sigstop) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001865 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001866#ifdef __WALL
1867 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1868 if (errno == ECHILD) /* Already gone. */
1869 break;
1870 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001871 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001872 break;
1873 }
1874#endif /* __WALL */
1875 /* No __WALL here. */
1876 if (waitpid(tcp->pid, &status, 0) < 0) {
1877 if (errno != ECHILD) {
1878 perror("detach: waiting");
1879 break;
1880 }
1881#ifdef __WCLONE
1882 /* If no processes, try clones. */
1883 if (wait4(tcp->pid, &status, __WCLONE,
1884 NULL) < 0) {
1885 if (errno != ECHILD)
1886 perror("detach: waiting");
1887 break;
1888 }
1889#endif /* __WCLONE */
1890 }
1891#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001892 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001893#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001894 if (!WIFSTOPPED(status)) {
1895 /* Au revoir, mon ami. */
1896 break;
1897 }
1898 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001899 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001900 break;
1901 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001902 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001903 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001904 : WSTOPSIG(status));
1905 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001908 }
Roland McGrath7bf10472002-12-16 20:42:50 +00001909#endif /* LINUX */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910
1911#if defined(SUNOS4)
1912 /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
Denys Vlasenko4c196382012-01-04 15:11:09 +01001913 error = ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914#endif /* SUNOS4 */
1915
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001916 if (!qflag)
1917 fprintf(stderr, "Process %u detached\n", tcp->pid);
1918
1919 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001920
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 return error;
1922}
1923
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001924#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001925
Dmitry V. Levine5e60852009-12-31 22:50:49 +00001926static void reaper(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927{
1928 int pid;
1929 int status;
1930
1931 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932 }
1933}
1934
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001935#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936
1937static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001938cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939{
1940 int i;
1941 struct tcb *tcp;
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001942 int fatal_sig = interrupted ? interrupted : SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001943
Roland McGrathee9d4352002-12-18 04:16:10 +00001944 for (i = 0; i < tcbtabsize; i++) {
1945 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001946 if (!(tcp->flags & TCB_INUSE))
1947 continue;
1948 if (debug)
1949 fprintf(stderr,
1950 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001951 if (printing_tcp &&
1952 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1953 tprints(" <unfinished ...>\n");
1954 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955 }
1956 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001957 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001958 else {
1959 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001960 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 }
1962 }
1963 if (cflag)
1964 call_summary(outf);
1965}
1966
1967static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001968interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001969{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001970 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971}
1972
1973#ifndef HAVE_STRERROR
1974
Roland McGrath6d2b3492002-12-30 00:51:30 +00001975#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976extern int sys_nerr;
1977extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001978#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001979
1980const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001981strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982{
1983 static char buf[64];
1984
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001985 if (err_no < 1 || err_no >= sys_nerr) {
1986 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001987 return buf;
1988 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001989 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001990}
1991
1992#endif /* HAVE_STERRROR */
1993
1994#ifndef HAVE_STRSIGNAL
1995
Roland McGrath8f474e02003-01-14 07:53:33 +00001996#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001997extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001999#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
2000extern char *_sys_siglist[];
2001#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002002
2003const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002004strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002005{
2006 static char buf[64];
2007
2008 if (sig < 1 || sig >= NSIG) {
2009 sprintf(buf, "Unknown signal %d", sig);
2010 return buf;
2011 }
2012#ifdef HAVE__SYS_SIGLIST
2013 return _sys_siglist[sig];
2014#else
2015 return sys_siglist[sig];
2016#endif
2017}
2018
2019#endif /* HAVE_STRSIGNAL */
2020
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002021#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002022
2023static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002024rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025{
2026 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002027
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02002028 free(pollv);
2029 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02002030 if (!pollv)
2031 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00002032
Roland McGrathca16be82003-01-10 19:55:28 +00002033 for (i = j = 0; i < tcbtabsize; i++) {
2034 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 if (!(tcp->flags & TCB_INUSE))
2036 continue;
2037 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002038 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039 j++;
2040 }
2041 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002042 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002043 }
2044}
2045
2046#ifndef HAVE_POLLABLE_PROCFS
2047
2048static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002049proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002051 int i;
2052
2053 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002054 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 }
2056 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02002057 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058 }
2059}
2060
2061static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002062proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002063{
2064 int i;
2065 int n;
2066 struct proc_pollfd pollinfo;
2067
Denys Vlasenko5d645812011-08-20 12:48:18 +02002068 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2069 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002070 return n;
2071 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002072 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002073 }
2074 for (i = 0; i < nprocs; i++) {
2075 if (pollv[i].fd == pollinfo.fd)
2076 pollv[i].revents = pollinfo.revents;
2077 else
2078 pollv[i].revents = 0;
2079 }
2080 poller_pid = pollinfo.pid;
2081 return 1;
2082}
2083
2084static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002085wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086{
2087}
2088
2089static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002090proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091{
2092 struct proc_pollfd pollinfo;
2093 struct sigaction sa;
2094 sigset_t blocked_set, empty_set;
2095 int i;
2096 int n;
2097 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002098#ifdef FREEBSD
2099 struct procfs_status pfs;
2100#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101
2102 switch (fork()) {
2103 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002104 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002105 case 0:
2106 break;
2107 default:
2108 return;
2109 }
2110
2111 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2112 sa.sa_flags = 0;
2113 sigemptyset(&sa.sa_mask);
2114 sigaction(SIGHUP, &sa, NULL);
2115 sigaction(SIGINT, &sa, NULL);
2116 sigaction(SIGQUIT, &sa, NULL);
2117 sigaction(SIGPIPE, &sa, NULL);
2118 sigaction(SIGTERM, &sa, NULL);
2119 sa.sa_handler = wakeup_handler;
2120 sigaction(SIGUSR1, &sa, NULL);
2121 sigemptyset(&blocked_set);
2122 sigaddset(&blocked_set, SIGUSR1);
2123 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2124 sigemptyset(&empty_set);
2125
2126 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002127 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 }
2129 n = rl.rlim_cur;
2130 for (i = 0; i < n; i++) {
2131 if (i != pfd && i != proc_poll_pipe[1])
2132 close(i);
2133 }
2134
2135 pollinfo.fd = pfd;
2136 pollinfo.pid = getpid();
2137 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002139 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2140#else
2141 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2142#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002143 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002144 switch (errno) {
2145 case EINTR:
2146 continue;
2147 case EBADF:
2148 pollinfo.revents = POLLERR;
2149 break;
2150 case ENOENT:
2151 pollinfo.revents = POLLHUP;
2152 break;
2153 default:
2154 perror("proc_poller: PIOCWSTOP");
2155 }
2156 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2157 _exit(0);
2158 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002159 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002160 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2161 sigsuspend(&empty_set);
2162 }
2163}
2164
2165#endif /* !HAVE_POLLABLE_PROCFS */
2166
2167static int
2168choose_pfd()
2169{
2170 int i, j;
2171 struct tcb *tcp;
2172
2173 static int last;
2174
2175 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002176 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002177 /*
2178 * The previous process is ready to run again. We'll
2179 * let it do so if it is currently in a syscall. This
2180 * heuristic improves the readability of the trace.
2181 */
2182 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002183 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002184 return pollv[last].fd;
2185 }
2186
2187 for (i = 0; i < nprocs; i++) {
2188 /* Let competing children run round robin. */
2189 j = (i + last + 1) % nprocs;
2190 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2191 tcp = pfd2tcb(pollv[j].fd);
2192 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002193 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002194 }
2195 droptcb(tcp);
2196 return -1;
2197 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002198 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 last = j;
2200 return pollv[j].fd;
2201 }
2202 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002203 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204}
2205
2206static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002207trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002208{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002209#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002210 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002211#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002212 struct tcb *tcp;
2213 int pfd;
2214 int what;
2215 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002216 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217
2218 for (;;) {
2219 if (interactive)
2220 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2221
2222 if (nprocs == 0)
2223 break;
2224
2225 switch (nprocs) {
2226 case 1:
2227#ifndef HAVE_POLLABLE_PROCFS
2228 if (proc_poll_pipe[0] == -1) {
2229#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002230 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002231 if (!tcp)
2232 continue;
2233 pfd = tcp->pfd;
2234 if (pfd == -1)
2235 continue;
2236 break;
2237#ifndef HAVE_POLLABLE_PROCFS
2238 }
2239 /* fall through ... */
2240#endif /* !HAVE_POLLABLE_PROCFS */
2241 default:
2242#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002243#ifdef POLL_HACK
2244 /* On some systems (e.g. UnixWare) we get too much ugly
2245 "unfinished..." stuff when multiple proceses are in
2246 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002247
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002248 if (in_syscall) {
2249 struct pollfd pv;
2250 tcp = in_syscall;
2251 in_syscall = NULL;
2252 pv.fd = tcp->pfd;
2253 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002254 what = poll(&pv, 1, 1);
2255 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002256 if (interrupted)
2257 return 0;
2258 continue;
2259 }
2260 else if (what == 1 && pv.revents & POLLWANT) {
2261 goto FOUND;
2262 }
2263 }
2264#endif
2265
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002266 if (poll(pollv, nprocs, INFTIM) < 0) {
2267 if (interrupted)
2268 return 0;
2269 continue;
2270 }
2271#else /* !HAVE_POLLABLE_PROCFS */
2272 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2273 if (interrupted)
2274 return 0;
2275 continue;
2276 }
2277#endif /* !HAVE_POLLABLE_PROCFS */
2278 pfd = choose_pfd();
2279 if (pfd == -1)
2280 continue;
2281 break;
2282 }
2283
2284 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002285 tcp = pfd2tcb(pfd);
2286 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002287 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288 }
John Hughesb6643082002-05-23 11:02:22 +00002289#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002290 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002291#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002292 /* Get the status of the process. */
2293 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002294#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002295 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002296#else /* FREEBSD */
2297 /* Thanks to some scheduling mystery, the first poller
2298 sometimes waits for the already processed end of fork
2299 event. Doing a non blocking poll here solves the problem. */
2300 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002301 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002302 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002303 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002304#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002305 ioctl_errno = errno;
2306#ifndef HAVE_POLLABLE_PROCFS
2307 if (proc_poll_pipe[0] != -1) {
2308 if (ioctl_result < 0)
2309 kill(poller_pid, SIGKILL);
2310 else
2311 kill(poller_pid, SIGUSR1);
2312 }
2313#endif /* !HAVE_POLLABLE_PROCFS */
2314 }
2315 if (interrupted)
2316 return 0;
2317
2318 if (interactive)
2319 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2320
2321 if (ioctl_result < 0) {
2322 /* Find out what happened if it failed. */
2323 switch (ioctl_errno) {
2324 case EINTR:
2325 case EBADF:
2326 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002327#ifdef FREEBSD
2328 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002329#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002330 case ENOENT:
2331 droptcb(tcp);
2332 continue;
2333 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002334 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002335 }
2336 }
2337
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002338#ifdef FREEBSD
2339 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2340 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002341 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002342 continue;
2343 }
Roland McGrath553a6092002-12-16 20:40:39 +00002344#endif
2345
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002346 /* clear the just started flag */
2347 tcp->flags &= ~TCB_STARTUP;
2348
2349 /* set current output file */
2350 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002351 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352
2353 if (cflag) {
2354 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002355#ifdef FREEBSD
2356 char buf[1024];
2357 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002358
Denys Vlasenko5d645812011-08-20 12:48:18 +02002359 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2360 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002361 buf[len] = '\0';
2362 sscanf(buf,
2363 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2364 &stime.tv_sec, &stime.tv_usec);
2365 } else
2366 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002367#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002368 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2369 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002370#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002371 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2372 tcp->stime = stime;
2373 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002374 what = tcp->status.PR_WHAT;
2375 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002376#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002377 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002378 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2379 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002380 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002381 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002382 }
2383 }
2384 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002385#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002386 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002387#ifdef POLL_HACK
2388 in_syscall = tcp;
2389#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 case PR_SYSEXIT:
2391 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002392 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002393 }
2394 break;
2395 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002396 if (cflag != CFLAG_ONLY_STATS
2397 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002399 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002400 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002401 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002402#ifdef PR_INFO
2403 if (tcp->status.PR_INFO.si_signo == what) {
2404 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002405 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002406 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002407 tprints("\n");
2408 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002409 }
2410#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002411 }
2412 break;
2413 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002414 if (cflag != CFLAGS_ONLY_STATS
2415 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002417 tprintf("=== FAULT %d ===\n", what);
2418 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419 }
2420 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002421#ifdef FREEBSD
2422 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002423 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002424#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002426 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002427 break;
2428 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002429 /* Remember current print column before continuing. */
2430 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002431 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002432#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002433 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002434#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002435 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002436#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002437 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002438 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002439 }
2440 }
2441 return 0;
2442}
2443
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002444#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002445
Roland McGratheb9e2e82009-06-02 16:49:22 -07002446static int
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002447trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002449#ifdef LINUX
2450 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002451 struct rusage *rup = cflag ? &ru : NULL;
2452# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002453 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002454# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002455#endif /* LINUX */
2456
Roland McGratheb9e2e82009-06-02 16:49:22 -07002457 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002458 int pid;
2459 int wait_errno;
2460 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002461 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002462 struct tcb *tcp;
2463 unsigned event;
2464
Denys Vlasenko222713a2009-03-17 14:29:59 +00002465 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002466 return 0;
2467 if (interactive)
2468 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002469#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002470# ifdef __WALL
2471 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002472 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002473 /* this kernel does not support __WALL */
2474 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002475 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002476 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002477 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002478 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002479 pid = wait4(-1, &status, __WCLONE, rup);
2480 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002481 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002482 }
2483 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002484# else
2485 pid = wait4(-1, &status, 0, rup);
2486# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002487#endif /* LINUX */
2488#ifdef SUNOS4
2489 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002490#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002491 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002492 if (interactive)
2493 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002494
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002495 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002496 switch (wait_errno) {
2497 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002498 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002499 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002500 /*
2501 * We would like to verify this case
2502 * but sometimes a race in Solbourne's
2503 * version of SunOS sometimes reports
2504 * ECHILD before sending us SIGCHILD.
2505 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002506 return 0;
2507 default:
2508 errno = wait_errno;
2509 perror("strace: wait");
2510 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002511 }
2512 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002513 if (pid == popen_pid) {
2514 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002515 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002516 continue;
2517 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002518
2519 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002520 if (debug) {
2521 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2522#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002523 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002524 static const char *const event_names[] = {
2525 [PTRACE_EVENT_CLONE] = "CLONE",
2526 [PTRACE_EVENT_FORK] = "FORK",
2527 [PTRACE_EVENT_VFORK] = "VFORK",
2528 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2529 [PTRACE_EVENT_EXEC] = "EXEC",
2530 [PTRACE_EVENT_EXIT] = "EXIT",
2531 };
2532 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002533 if (event < ARRAY_SIZE(event_names))
2534 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002535 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002536 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002537 e = buf;
2538 }
2539 fprintf(stderr, " PTRACE_EVENT_%s", e);
2540 }
2541#endif
2542 strcpy(buf, "???");
2543 if (WIFSIGNALED(status))
2544#ifdef WCOREDUMP
2545 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2546 WCOREDUMP(status) ? "core," : "",
2547 signame(WTERMSIG(status)));
2548#else
2549 sprintf(buf, "WIFSIGNALED,sig=%s",
2550 signame(WTERMSIG(status)));
2551#endif
2552 if (WIFEXITED(status))
2553 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2554 if (WIFSTOPPED(status))
2555 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002556#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002557 if (WIFCONTINUED(status))
2558 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002559#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002560 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2561 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002562
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002563 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002564 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002565
2566#ifdef LINUX
2567 /* Under Linux, execve changes pid to thread leader's pid,
2568 * and we see this changed pid on EVENT_EXEC and later,
2569 * execve sysexit. Leader "disappears" without exit
2570 * notification. Let user know that, drop leader's tcb,
2571 * and fix up pid in execve thread's tcb.
2572 * Effectively, execve thread's tcb replaces leader's tcb.
2573 *
2574 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2575 * on exit syscall) in multithreaded programs exactly
2576 * in order to handle this case.
2577 *
2578 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2579 * On 2.6 and earlier, it can return garbage.
2580 */
2581 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2582 long old_pid = 0;
2583 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2584 && old_pid > 0
2585 && old_pid != pid
2586 ) {
2587 struct tcb *execve_thread = pid2tcb(old_pid);
2588 if (tcp) {
2589 outf = tcp->outf;
2590 curcol = tcp->curcol;
2591 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002592 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002593 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002594 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002595 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2596 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002597 fflush(outf);
2598 }
2599 if (execve_thread) {
2600 /* swap output FILEs (needed for -ff) */
2601 tcp->outf = execve_thread->outf;
2602 execve_thread->outf = outf;
2603 }
2604 droptcb(tcp);
2605 }
2606 tcp = execve_thread;
2607 if (tcp) {
2608 tcp->pid = pid;
2609 tcp->flags |= TCB_REPRINT;
2610 }
2611 }
2612 }
2613#endif
2614
Denys Vlasenko5d645812011-08-20 12:48:18 +02002615 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002616#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002617 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002618 /* This is needed to go with the CLONE_PTRACE
2619 changes in process.c/util.c: we might see
2620 the child's initial trap before we see the
2621 parent return from the clone syscall.
2622 Leave the child suspended until the parent
2623 returns from its system call. Only then
2624 will we have the association of parent and
2625 child so that we know how to do clearbpt
2626 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002627 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002628 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002629 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002630 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002631 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002632 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002633 else
2634 /* This can happen if a clone call used
2635 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002636#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002637 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002638 if (WIFSTOPPED(status))
2639 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002640 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002641 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002642 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002643 /* set current output file */
2644 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002645 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002646#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002647 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2649 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002650 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002651#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002652
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002653 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002654 if (pid == strace_child)
2655 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002656 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002657 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2658 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002659#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002660 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002661 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002662 WCOREDUMP(status) ? "(core dumped) " : "");
2663#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002664 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002665 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002666#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002667 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002668 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002669 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002670 droptcb(tcp);
2671 continue;
2672 }
2673 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002674 if (pid == strace_child)
2675 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002676 if (tcp == printing_tcp) {
2677 tprints(" <unfinished ...>\n");
2678 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002679 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002680 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2681 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002682 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2683 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002684 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002685 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002686 droptcb(tcp);
2687 continue;
2688 }
2689 if (!WIFSTOPPED(status)) {
2690 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2691 droptcb(tcp);
2692 continue;
2693 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002695 /* Is this the very first time we see this tracee stopped? */
2696 if (tcp->flags & TCB_STARTUP) {
2697 if (debug)
2698 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002700 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002701 /*
2702 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002703 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002704 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002705 if (clearbpt(tcp) < 0) {
2706 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002707 droptcb(tcp);
2708 cleanup();
2709 return -1;
2710 }
2711 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002712#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002713 if (ptrace_setoptions) {
2714 if (debug)
2715 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2716 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2717 if (errno != ESRCH) {
2718 /* Should never happen, really */
2719 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002720 }
2721 }
2722 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002723#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002724 }
2725
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002726 sig = WSTOPSIG(status);
2727
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002728 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002729 /* Ptrace event */
2730#ifdef USE_SEIZE
2731 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01002732 /*
2733 * PTRACE_INTERRUPT-stop or group-stop.
2734 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
2735 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002736 if (sig == SIGSTOP
2737 || sig == SIGTSTP
2738 || sig == SIGTTIN
2739 || sig == SIGTTOU
2740 ) {
2741 stopped = 1;
2742 goto show_stopsig;
2743 }
2744 }
2745#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002746 goto restart_tracee_with_sig_0;
2747 }
2748
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002749 /* Is this post-attach SIGSTOP?
2750 * Interestingly, the process may stop
2751 * with STOPSIG equal to some other signal
2752 * than SIGSTOP if we happend to attach
2753 * just before the process takes a signal.
2754 */
2755 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2756 if (debug)
2757 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2758 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002759 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002760 }
2761
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002762 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002763 siginfo_t si;
2764
2765 /* Nonzero (true) if tracee is stopped by signal
2766 * (as opposed to "tracee received signal").
2767 */
2768 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002769#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002770 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002771#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002772 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002773 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002774#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002775 long pc = 0;
2776 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002777
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002778 upeek(tcp, PT_CR_IPSR, &psr);
2779 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002780
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002781# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002782 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002783# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002784# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002785#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002786# define PC_FORMAT_STR ""
2787# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002788#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002789 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002790 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002791 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002792 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002793 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002794 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002795 PC_FORMAT_ARG);
2796 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002797 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002798 strsignal(sig),
2799 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002800 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002801 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002802 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002803 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002804
2805 if (!stopped)
2806 /* It's signal-delivery-stop. Inject the signal */
2807 goto restart_tracee;
2808
2809 /* It's group-stop */
2810#ifdef USE_SEIZE
2811 if (use_seize) {
2812 /*
2813 * This ends ptrace-stop, but does *not* end group-stop.
2814 * This makes stopping signals work properly on straced process
2815 * (that is, process really stops. It used to continue to run).
2816 */
2817 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2818 cleanup();
2819 return -1;
2820 }
2821 continue;
2822 }
2823 /* We don't have PTRACE_LISTEN support... */
2824#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002825 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002826 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002827
2828 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002829 if (interrupted)
2830 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002831
2832 /* This should be syscall entry or exit.
2833 * (Or it still can be that pesky post-execve SIGTRAP!)
2834 * Handle it.
2835 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002836 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2837 /* ptrace() failed in trace_syscall() with ESRCH.
2838 * Likely a result of process disappearing mid-flight.
2839 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002840 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002841 */
2842 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002843 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002844 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002845 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002846 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002847 printing_tcp->flags |= TCB_REPRINT;
2848 tprints(" <unfinished ...>\n");
2849 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002850 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002851 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002852 /* We assume that ptrace error was caused by process death.
2853 * We used to detach(tcp) here, but since we no longer
2854 * implement "detach before death" policy/hack,
2855 * we can let this process to report its death to us
2856 * normally, via WIFEXITED or WIFSIGNALED wait status.
2857 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002858 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002859 /* It's our real child (and we also trace it) */
2860 /* my_tkill(pid, SIGKILL); - why? */
2861 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002862 }
2863 continue;
2864 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002865 restart_tracee_with_sig_0:
2866 sig = 0;
2867 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002868 /* Remember current print column before continuing. */
2869 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002870 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002871 cleanup();
2872 return -1;
2873 }
2874 }
2875 return 0;
2876}
2877
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002878#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002879
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002880void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002881tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002882{
2883 va_list args;
2884
Andreas Schwabe5355de2009-10-27 16:56:43 +01002885 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002886 if (outf) {
2887 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002888 if (n < 0) {
2889 if (outf != stderr)
2890 perror(outfname == NULL
2891 ? "<writing to pipe>" : outfname);
2892 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002893 curcol += n;
2894 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002895 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002896}
2897
2898void
2899tprints(const char *str)
2900{
2901 if (outf) {
2902 int n = fputs(str, outf);
2903 if (n >= 0) {
2904 curcol += strlen(str);
2905 return;
2906 }
2907 if (outf != stderr)
2908 perror(outfname == NULL
2909 ? "<writing to pipe>" : outfname);
2910 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002911}
2912
2913void
Denys Vlasenko12014262011-05-30 14:00:14 +02002914printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002915{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002916 if (printing_tcp) {
2917 if (printing_tcp->ptrace_errno) {
2918 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002919 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002920 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002921 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002922 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002923 printing_tcp->ptrace_errno = 0;
2924 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2925 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002926 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002927 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002928 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002929
2930 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002931 curcol = 0;
2932 if ((followfork == 1 || pflag_seen > 1) && outfname)
2933 tprintf("%-5d ", tcp->pid);
2934 else if (nprocs > 1 && !outfname)
2935 tprintf("[pid %5u] ", tcp->pid);
2936 if (tflag) {
2937 char str[sizeof("HH:MM:SS")];
2938 struct timeval tv, dtv;
2939 static struct timeval otv;
2940
2941 gettimeofday(&tv, NULL);
2942 if (rflag) {
2943 if (otv.tv_sec == 0)
2944 otv = tv;
2945 tv_sub(&dtv, &tv, &otv);
2946 tprintf("%6ld.%06ld ",
2947 (long) dtv.tv_sec, (long) dtv.tv_usec);
2948 otv = tv;
2949 }
2950 else if (tflag > 2) {
2951 tprintf("%ld.%06ld ",
2952 (long) tv.tv_sec, (long) tv.tv_usec);
2953 }
2954 else {
2955 time_t local = tv.tv_sec;
2956 strftime(str, sizeof(str), "%T", localtime(&local));
2957 if (tflag > 1)
2958 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2959 else
2960 tprintf("%s ", str);
2961 }
2962 }
2963 if (iflag)
2964 printcall(tcp);
2965}
2966
2967void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002968tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002969{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002970 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002971 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002972}
2973
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002974#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002975
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002976int
2977mp_ioctl(int fd, int cmd, void *arg, int size)
2978{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002979 struct iovec iov[2];
2980 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002981
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002982 iov[0].iov_base = &cmd;
2983 iov[0].iov_len = sizeof cmd;
2984 if (arg) {
2985 ++n;
2986 iov[1].iov_base = arg;
2987 iov[1].iov_len = size;
2988 }
Roland McGrath553a6092002-12-16 20:40:39 +00002989
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002990 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002991}
2992
2993#endif