blob: 26d7010f1fc1ccd38e56d8182a4a1a2633e6fb10 [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;
152#else /* !HAVE_SIG_ATOMIC_T */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153static volatile int interrupted;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154#endif /* !HAVE_SIG_ATOMIC_T */
155
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;
1942
Roland McGrathee9d4352002-12-18 04:16:10 +00001943 for (i = 0; i < tcbtabsize; i++) {
1944 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001945 if (!(tcp->flags & TCB_INUSE))
1946 continue;
1947 if (debug)
1948 fprintf(stderr,
1949 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001950 if (printing_tcp &&
1951 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1952 tprints(" <unfinished ...>\n");
1953 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954 }
1955 if (tcp->flags & TCB_ATTACHED)
Denys Vlasenko4c196382012-01-04 15:11:09 +01001956 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957 else {
1958 kill(tcp->pid, SIGCONT);
1959 kill(tcp->pid, SIGTERM);
1960 }
1961 }
1962 if (cflag)
1963 call_summary(outf);
1964}
1965
1966static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001967interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001968{
1969 interrupted = 1;
1970}
1971
1972#ifndef HAVE_STRERROR
1973
Roland McGrath6d2b3492002-12-30 00:51:30 +00001974#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975extern int sys_nerr;
1976extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001977#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978
1979const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001980strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001981{
1982 static char buf[64];
1983
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001984 if (err_no < 1 || err_no >= sys_nerr) {
1985 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001986 return buf;
1987 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001988 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989}
1990
1991#endif /* HAVE_STERRROR */
1992
1993#ifndef HAVE_STRSIGNAL
1994
Roland McGrath8f474e02003-01-14 07:53:33 +00001995#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001996extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001997#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001998#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1999extern char *_sys_siglist[];
2000#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002001
2002const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02002003strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004{
2005 static char buf[64];
2006
2007 if (sig < 1 || sig >= NSIG) {
2008 sprintf(buf, "Unknown signal %d", sig);
2009 return buf;
2010 }
2011#ifdef HAVE__SYS_SIGLIST
2012 return _sys_siglist[sig];
2013#else
2014 return sys_siglist[sig];
2015#endif
2016}
2017
2018#endif /* HAVE_STRSIGNAL */
2019
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002020#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021
2022static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002023rebuild_pollv(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024{
2025 int i, j;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002026
Denys Vlasenkocfd364b2011-08-20 13:41:13 +02002027 free(pollv);
2028 pollv = malloc(nprocs * sizeof(pollv[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02002029 if (!pollv)
2030 die_out_of_memory();
Roland McGrathee9d4352002-12-18 04:16:10 +00002031
Roland McGrathca16be82003-01-10 19:55:28 +00002032 for (i = j = 0; i < tcbtabsize; i++) {
2033 struct tcb *tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002034 if (!(tcp->flags & TCB_INUSE))
2035 continue;
2036 pollv[j].fd = tcp->pfd;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002037 pollv[j].events = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002038 j++;
2039 }
2040 if (j != nprocs) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002041 error_msg_and_die("proc miscount");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002042 }
2043}
2044
2045#ifndef HAVE_POLLABLE_PROCFS
2046
2047static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002048proc_poll_open(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002050 int i;
2051
2052 if (pipe(proc_poll_pipe) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002053 perror_msg_and_die("pipe");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 }
2055 for (i = 0; i < 2; i++) {
Denys Vlasenko1f532ab2011-06-22 13:11:23 +02002056 set_cloexec_flag(proc_poll_pipe[i]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057 }
2058}
2059
2060static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002061proc_poll(struct pollfd *pollv, int nfds, int timeout)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002062{
2063 int i;
2064 int n;
2065 struct proc_pollfd pollinfo;
2066
Denys Vlasenko5d645812011-08-20 12:48:18 +02002067 n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
2068 if (n < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002069 return n;
2070 if (n != sizeof(struct proc_pollfd)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002071 error_msg_and_die("panic: short read: %d", n);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002072 }
2073 for (i = 0; i < nprocs; i++) {
2074 if (pollv[i].fd == pollinfo.fd)
2075 pollv[i].revents = pollinfo.revents;
2076 else
2077 pollv[i].revents = 0;
2078 }
2079 poller_pid = pollinfo.pid;
2080 return 1;
2081}
2082
2083static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002084wakeup_handler(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002085{
2086}
2087
2088static void
Denys Vlasenko12014262011-05-30 14:00:14 +02002089proc_poller(int pfd)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090{
2091 struct proc_pollfd pollinfo;
2092 struct sigaction sa;
2093 sigset_t blocked_set, empty_set;
2094 int i;
2095 int n;
2096 struct rlimit rl;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002097#ifdef FREEBSD
2098 struct procfs_status pfs;
2099#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100
2101 switch (fork()) {
2102 case -1:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002103 perror_msg_and_die("fork");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104 case 0:
2105 break;
2106 default:
2107 return;
2108 }
2109
2110 sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
2111 sa.sa_flags = 0;
2112 sigemptyset(&sa.sa_mask);
2113 sigaction(SIGHUP, &sa, NULL);
2114 sigaction(SIGINT, &sa, NULL);
2115 sigaction(SIGQUIT, &sa, NULL);
2116 sigaction(SIGPIPE, &sa, NULL);
2117 sigaction(SIGTERM, &sa, NULL);
2118 sa.sa_handler = wakeup_handler;
2119 sigaction(SIGUSR1, &sa, NULL);
2120 sigemptyset(&blocked_set);
2121 sigaddset(&blocked_set, SIGUSR1);
2122 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2123 sigemptyset(&empty_set);
2124
2125 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002126 perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127 }
2128 n = rl.rlim_cur;
2129 for (i = 0; i < n; i++) {
2130 if (i != pfd && i != proc_poll_pipe[1])
2131 close(i);
2132 }
2133
2134 pollinfo.fd = pfd;
2135 pollinfo.pid = getpid();
2136 for (;;) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002137#ifndef FREEBSD
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002138 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
2139#else
2140 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
2141#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002142 {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143 switch (errno) {
2144 case EINTR:
2145 continue;
2146 case EBADF:
2147 pollinfo.revents = POLLERR;
2148 break;
2149 case ENOENT:
2150 pollinfo.revents = POLLHUP;
2151 break;
2152 default:
2153 perror("proc_poller: PIOCWSTOP");
2154 }
2155 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2156 _exit(0);
2157 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002158 pollinfo.revents = POLLWANT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002159 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
2160 sigsuspend(&empty_set);
2161 }
2162}
2163
2164#endif /* !HAVE_POLLABLE_PROCFS */
2165
2166static int
2167choose_pfd()
2168{
2169 int i, j;
2170 struct tcb *tcp;
2171
2172 static int last;
2173
2174 if (followfork < 2 &&
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002175 last < nprocs && (pollv[last].revents & POLLWANT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002176 /*
2177 * The previous process is ready to run again. We'll
2178 * let it do so if it is currently in a syscall. This
2179 * heuristic improves the readability of the trace.
2180 */
2181 tcp = pfd2tcb(pollv[last].fd);
Denys Vlasenkob88f9612011-08-21 18:03:23 +02002182 if (tcp && exiting(tcp))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002183 return pollv[last].fd;
2184 }
2185
2186 for (i = 0; i < nprocs; i++) {
2187 /* Let competing children run round robin. */
2188 j = (i + last + 1) % nprocs;
2189 if (pollv[j].revents & (POLLHUP | POLLERR)) {
2190 tcp = pfd2tcb(pollv[j].fd);
2191 if (!tcp) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002192 error_msg_and_die("lost proc");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002193 }
2194 droptcb(tcp);
2195 return -1;
2196 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002197 if (pollv[j].revents & POLLWANT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002198 last = j;
2199 return pollv[j].fd;
2200 }
2201 }
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002202 error_msg_and_die("nothing ready");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203}
2204
2205static int
Denys Vlasenko12014262011-05-30 14:00:14 +02002206trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207{
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002208#ifdef POLL_HACK
John Hughesd870b3c2002-05-21 11:24:18 +00002209 struct tcb *in_syscall = NULL;
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002210#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 struct tcb *tcp;
2212 int pfd;
2213 int what;
2214 int ioctl_result = 0, ioctl_errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002215 long arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002216
2217 for (;;) {
2218 if (interactive)
2219 sigprocmask(SIG_SETMASK, &empty_set, NULL);
2220
2221 if (nprocs == 0)
2222 break;
2223
2224 switch (nprocs) {
2225 case 1:
2226#ifndef HAVE_POLLABLE_PROCFS
2227 if (proc_poll_pipe[0] == -1) {
2228#endif
Roland McGrath54e931f2010-09-14 18:59:20 -07002229 tcp = first_used_tcb();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002230 if (!tcp)
2231 continue;
2232 pfd = tcp->pfd;
2233 if (pfd == -1)
2234 continue;
2235 break;
2236#ifndef HAVE_POLLABLE_PROCFS
2237 }
2238 /* fall through ... */
2239#endif /* !HAVE_POLLABLE_PROCFS */
2240 default:
2241#ifdef HAVE_POLLABLE_PROCFS
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002242#ifdef POLL_HACK
2243 /* On some systems (e.g. UnixWare) we get too much ugly
2244 "unfinished..." stuff when multiple proceses are in
2245 syscalls. Here's a nasty hack */
Roland McGrath553a6092002-12-16 20:40:39 +00002246
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002247 if (in_syscall) {
2248 struct pollfd pv;
2249 tcp = in_syscall;
2250 in_syscall = NULL;
2251 pv.fd = tcp->pfd;
2252 pv.events = POLLWANT;
Denys Vlasenko5d645812011-08-20 12:48:18 +02002253 what = poll(&pv, 1, 1);
2254 if (what < 0) {
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002255 if (interrupted)
2256 return 0;
2257 continue;
2258 }
2259 else if (what == 1 && pv.revents & POLLWANT) {
2260 goto FOUND;
2261 }
2262 }
2263#endif
2264
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002265 if (poll(pollv, nprocs, INFTIM) < 0) {
2266 if (interrupted)
2267 return 0;
2268 continue;
2269 }
2270#else /* !HAVE_POLLABLE_PROCFS */
2271 if (proc_poll(pollv, nprocs, INFTIM) < 0) {
2272 if (interrupted)
2273 return 0;
2274 continue;
2275 }
2276#endif /* !HAVE_POLLABLE_PROCFS */
2277 pfd = choose_pfd();
2278 if (pfd == -1)
2279 continue;
2280 break;
2281 }
2282
2283 /* Look up `pfd' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002284 tcp = pfd2tcb(pfd);
2285 if (tcp == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002286 error_msg_and_die("unknown pfd: %u", pfd);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287 }
John Hughesb6643082002-05-23 11:02:22 +00002288#ifdef POLL_HACK
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002289 FOUND:
John Hughesb6643082002-05-23 11:02:22 +00002290#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002291 /* Get the status of the process. */
2292 if (!interrupted) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002293#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002294 ioctl_result = IOCTL_WSTOP(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002295#else /* FREEBSD */
2296 /* Thanks to some scheduling mystery, the first poller
2297 sometimes waits for the already processed end of fork
2298 event. Doing a non blocking poll here solves the problem. */
2299 if (proc_poll_pipe[0] != -1)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002300 ioctl_result = IOCTL_STATUS(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002301 else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002302 ioctl_result = IOCTL_WSTOP(tcp);
Roland McGrath553a6092002-12-16 20:40:39 +00002303#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304 ioctl_errno = errno;
2305#ifndef HAVE_POLLABLE_PROCFS
2306 if (proc_poll_pipe[0] != -1) {
2307 if (ioctl_result < 0)
2308 kill(poller_pid, SIGKILL);
2309 else
2310 kill(poller_pid, SIGUSR1);
2311 }
2312#endif /* !HAVE_POLLABLE_PROCFS */
2313 }
2314 if (interrupted)
2315 return 0;
2316
2317 if (interactive)
2318 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
2319
2320 if (ioctl_result < 0) {
2321 /* Find out what happened if it failed. */
2322 switch (ioctl_errno) {
2323 case EINTR:
2324 case EBADF:
2325 continue;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002326#ifdef FREEBSD
2327 case ENOTTY:
Roland McGrath553a6092002-12-16 20:40:39 +00002328#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 case ENOENT:
2330 droptcb(tcp);
2331 continue;
2332 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002333 perror_msg_and_die("PIOCWSTOP");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 }
2335 }
2336
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002337#ifdef FREEBSD
2338 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
2339 /* discard first event for a syscall we never entered */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002340 IOCTL(tcp->pfd, PIOCRUN, 0);
Wichert Akkerman2e4ffe52000-09-03 23:57:48 +00002341 continue;
2342 }
Roland McGrath553a6092002-12-16 20:40:39 +00002343#endif
2344
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 /* clear the just started flag */
2346 tcp->flags &= ~TCB_STARTUP;
2347
2348 /* set current output file */
2349 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002350 curcol = tcp->curcol;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002351
2352 if (cflag) {
2353 struct timeval stime;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002354#ifdef FREEBSD
2355 char buf[1024];
2356 int len;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002357
Denys Vlasenko5d645812011-08-20 12:48:18 +02002358 len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
2359 if (len > 0) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002360 buf[len] = '\0';
2361 sscanf(buf,
2362 "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2363 &stime.tv_sec, &stime.tv_usec);
2364 } else
2365 stime.tv_sec = stime.tv_usec = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002366#else /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002367 stime.tv_sec = tcp->status.pr_stime.tv_sec;
2368 stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002369#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002370 tv_sub(&tcp->dtime, &stime, &tcp->stime);
2371 tcp->stime = stime;
2372 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002373 what = tcp->status.PR_WHAT;
2374 switch (tcp->status.PR_WHY) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002375#ifndef FREEBSD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002376 case PR_REQUESTED:
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002377 if (tcp->status.PR_FLAGS & PR_ASLEEP) {
2378 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002379 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002380 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002381 }
2382 }
2383 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002384#endif /* !FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002385 case PR_SYSENTRY:
Wichert Akkerman9dbf1541999-11-26 13:11:29 +00002386#ifdef POLL_HACK
2387 in_syscall = tcp;
2388#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002389 case PR_SYSEXIT:
2390 if (trace_syscall(tcp) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002391 error_msg_and_die("syscall trouble");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002392 }
2393 break;
2394 case PR_SIGNALLED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002395 if (cflag != CFLAG_ONLY_STATS
2396 && (qual_flags[what] & QUAL_SIGNAL)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002397 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002398 tprintf("--- %s (%s) ---\n",
Nate Sammonsce780fc1999-03-29 23:23:13 +00002399 signame(what), strsignal(what));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002400 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002401#ifdef PR_INFO
2402 if (tcp->status.PR_INFO.si_signo == what) {
2403 printleader(tcp);
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002404 tprints(" siginfo=");
John Hughes58265892001-10-18 15:13:53 +00002405 printsiginfo(&tcp->status.PR_INFO, 1);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002406 tprints("\n");
2407 printing_tcp = NULL;
John Hughes58265892001-10-18 15:13:53 +00002408 }
2409#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002410 }
2411 break;
2412 case PR_FAULTED:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002413 if (cflag != CFLAGS_ONLY_STATS
2414 && (qual_flags[what] & QUAL_FAULT)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002415 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002416 tprintf("=== FAULT %d ===\n", what);
2417 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002418 }
2419 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002420#ifdef FREEBSD
2421 case 0: /* handle case we polled for nothing */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002422 continue;
Roland McGrath553a6092002-12-16 20:40:39 +00002423#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002424 default:
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002425 error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002426 break;
2427 }
Andreas Schwabccdff482009-10-27 16:27:13 +01002428 /* Remember current print column before continuing. */
2429 tcp->curcol = curcol;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002430 arg = 0;
Roland McGrath553a6092002-12-16 20:40:39 +00002431#ifndef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002432 if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002433#else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002434 if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
Roland McGrath553a6092002-12-16 20:40:39 +00002435#endif
Andreas Schwab372cc842010-07-09 11:49:27 +02002436 {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002437 perror_msg_and_die("PIOCRUN");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 }
2439 }
2440 return 0;
2441}
2442
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002443#else /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444
Roland McGratheb9e2e82009-06-02 16:49:22 -07002445static int
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002446trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002447{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002448#ifdef LINUX
2449 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002450 struct rusage *rup = cflag ? &ru : NULL;
2451# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07002452 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002453# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002454#endif /* LINUX */
2455
Roland McGratheb9e2e82009-06-02 16:49:22 -07002456 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002457 int pid;
2458 int wait_errno;
2459 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002460 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002461 struct tcb *tcp;
2462 unsigned event;
2463
Denys Vlasenko222713a2009-03-17 14:29:59 +00002464 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002465 return 0;
2466 if (interactive)
2467 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002468#ifdef LINUX
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002469# ifdef __WALL
2470 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00002471 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002472 /* this kernel does not support __WALL */
2473 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002474 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002475 }
Roland McGrath5bc05552002-12-17 04:50:47 +00002476 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002477 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002478 pid = wait4(-1, &status, __WCLONE, rup);
2479 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002480 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00002481 }
2482 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002483# else
2484 pid = wait4(-1, &status, 0, rup);
2485# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002486#endif /* LINUX */
2487#ifdef SUNOS4
2488 pid = wait(&status);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002489#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002490 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002491 if (interactive)
2492 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002493
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02002494 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002495 switch (wait_errno) {
2496 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002497 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002498 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002499 /*
2500 * We would like to verify this case
2501 * but sometimes a race in Solbourne's
2502 * version of SunOS sometimes reports
2503 * ECHILD before sending us SIGCHILD.
2504 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002505 return 0;
2506 default:
2507 errno = wait_errno;
2508 perror("strace: wait");
2509 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 }
2511 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002512 if (pid == popen_pid) {
2513 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02002514 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00002515 continue;
2516 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002517
2518 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002519 if (debug) {
2520 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
2521#ifdef LINUX
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002522 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002523 static const char *const event_names[] = {
2524 [PTRACE_EVENT_CLONE] = "CLONE",
2525 [PTRACE_EVENT_FORK] = "FORK",
2526 [PTRACE_EVENT_VFORK] = "VFORK",
2527 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
2528 [PTRACE_EVENT_EXEC] = "EXEC",
2529 [PTRACE_EVENT_EXIT] = "EXIT",
2530 };
2531 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002532 if (event < ARRAY_SIZE(event_names))
2533 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002534 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002535 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002536 e = buf;
2537 }
2538 fprintf(stderr, " PTRACE_EVENT_%s", e);
2539 }
2540#endif
2541 strcpy(buf, "???");
2542 if (WIFSIGNALED(status))
2543#ifdef WCOREDUMP
2544 sprintf(buf, "WIFSIGNALED,%ssig=%s",
2545 WCOREDUMP(status) ? "core," : "",
2546 signame(WTERMSIG(status)));
2547#else
2548 sprintf(buf, "WIFSIGNALED,sig=%s",
2549 signame(WTERMSIG(status)));
2550#endif
2551 if (WIFEXITED(status))
2552 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
2553 if (WIFSTOPPED(status))
2554 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002555#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002556 if (WIFCONTINUED(status))
2557 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02002558#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02002559 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
2560 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002561
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002562 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02002563 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002564
2565#ifdef LINUX
2566 /* Under Linux, execve changes pid to thread leader's pid,
2567 * and we see this changed pid on EVENT_EXEC and later,
2568 * execve sysexit. Leader "disappears" without exit
2569 * notification. Let user know that, drop leader's tcb,
2570 * and fix up pid in execve thread's tcb.
2571 * Effectively, execve thread's tcb replaces leader's tcb.
2572 *
2573 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2574 * on exit syscall) in multithreaded programs exactly
2575 * in order to handle this case.
2576 *
2577 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2578 * On 2.6 and earlier, it can return garbage.
2579 */
2580 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2581 long old_pid = 0;
2582 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2583 && old_pid > 0
2584 && old_pid != pid
2585 ) {
2586 struct tcb *execve_thread = pid2tcb(old_pid);
2587 if (tcp) {
2588 outf = tcp->outf;
2589 curcol = tcp->curcol;
2590 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002591 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002592 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002593 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002594 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2595 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002596 fflush(outf);
2597 }
2598 if (execve_thread) {
2599 /* swap output FILEs (needed for -ff) */
2600 tcp->outf = execve_thread->outf;
2601 execve_thread->outf = outf;
2602 }
2603 droptcb(tcp);
2604 }
2605 tcp = execve_thread;
2606 if (tcp) {
2607 tcp->pid = pid;
2608 tcp->flags |= TCB_REPRINT;
2609 }
2610 }
2611 }
2612#endif
2613
Denys Vlasenko5d645812011-08-20 12:48:18 +02002614 if (tcp == NULL) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002615#ifdef LINUX
Roland McGrath41c48222008-07-18 00:25:10 +00002616 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002617 /* This is needed to go with the CLONE_PTRACE
2618 changes in process.c/util.c: we might see
2619 the child's initial trap before we see the
2620 parent return from the clone syscall.
2621 Leave the child suspended until the parent
2622 returns from its system call. Only then
2623 will we have the association of parent and
2624 child so that we know how to do clearbpt
2625 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00002626 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002627 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002628 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02002629 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002630 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002631 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002632 else
2633 /* This can happen if a clone call used
2634 CLONE_PTRACE itself. */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002635#endif
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002636 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002637 if (WIFSTOPPED(status))
2638 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02002639 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00002640 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002641 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07002642 /* set current output file */
2643 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01002644 curcol = tcp->curcol;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002645#ifdef LINUX
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002646 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002647 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
2648 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002649 }
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002650#endif
Roland McGratheb9e2e82009-06-02 16:49:22 -07002651
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002652 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002653 if (pid == strace_child)
2654 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002655 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002656 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
2657 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002658#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01002659 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00002660 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002661 WCOREDUMP(status) ? "(core dumped) " : "");
2662#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002663 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02002664 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00002665#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01002666 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002667 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002668 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002669 droptcb(tcp);
2670 continue;
2671 }
2672 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00002673 if (pid == strace_child)
2674 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002675 if (tcp == printing_tcp) {
2676 tprints(" <unfinished ...>\n");
2677 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00002678 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002679 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
2680 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002681 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2682 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02002683 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002684 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002685 droptcb(tcp);
2686 continue;
2687 }
2688 if (!WIFSTOPPED(status)) {
2689 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
2690 droptcb(tcp);
2691 continue;
2692 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002693
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002694 /* Is this the very first time we see this tracee stopped? */
2695 if (tcp->flags & TCB_STARTUP) {
2696 if (debug)
2697 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002698 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00002700 /*
2701 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002702 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00002703 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002704 if (clearbpt(tcp) < 0) {
2705 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 droptcb(tcp);
2707 cleanup();
2708 return -1;
2709 }
2710 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002711#ifdef LINUX
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02002712 if (ptrace_setoptions) {
2713 if (debug)
2714 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2715 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2716 if (errno != ESRCH) {
2717 /* Should never happen, really */
2718 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02002719 }
2720 }
2721 }
Wang Chaoca8ab8d2010-11-12 17:26:08 +08002722#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002723 }
2724
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002725 sig = WSTOPSIG(status);
2726
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01002727 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002728 /* Ptrace event */
2729#ifdef USE_SEIZE
2730 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
2731 if (sig == SIGSTOP
2732 || sig == SIGTSTP
2733 || sig == SIGTTIN
2734 || sig == SIGTTOU
2735 ) {
2736 stopped = 1;
2737 goto show_stopsig;
2738 }
2739 }
2740#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002741 goto restart_tracee_with_sig_0;
2742 }
2743
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002744 /* Is this post-attach SIGSTOP?
2745 * Interestingly, the process may stop
2746 * with STOPSIG equal to some other signal
2747 * than SIGSTOP if we happend to attach
2748 * just before the process takes a signal.
2749 */
2750 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2751 if (debug)
2752 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2753 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002754 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002755 }
2756
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002757 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002758 siginfo_t si;
2759
2760 /* Nonzero (true) if tracee is stopped by signal
2761 * (as opposed to "tracee received signal").
2762 */
2763 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
2764 show_stopsig:
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002765 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002766 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002767#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002768 long pc = 0;
2769 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002770
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002771 upeek(tcp, PT_CR_IPSR, &psr);
2772 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002773
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002774# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002775 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002776# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002777# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002778#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002779# define PC_FORMAT_STR ""
2780# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002781#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002782 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002783 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002784 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002785 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002786 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002787 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002788 PC_FORMAT_ARG);
2789 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002790 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002791 strsignal(sig),
2792 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002793 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002794 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002795 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002796 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002797
2798 if (!stopped)
2799 /* It's signal-delivery-stop. Inject the signal */
2800 goto restart_tracee;
2801
2802 /* It's group-stop */
2803#ifdef USE_SEIZE
2804 if (use_seize) {
2805 /*
2806 * This ends ptrace-stop, but does *not* end group-stop.
2807 * This makes stopping signals work properly on straced process
2808 * (that is, process really stops. It used to continue to run).
2809 */
2810 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2811 cleanup();
2812 return -1;
2813 }
2814 continue;
2815 }
2816 /* We don't have PTRACE_LISTEN support... */
2817#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002818 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002819 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002820
2821 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002822 if (interrupted)
2823 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002824
2825 /* This should be syscall entry or exit.
2826 * (Or it still can be that pesky post-execve SIGTRAP!)
2827 * Handle it.
2828 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002829 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2830 /* ptrace() failed in trace_syscall() with ESRCH.
2831 * Likely a result of process disappearing mid-flight.
2832 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002833 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002834 */
2835 if (tcp->flags & TCB_ATTACHED) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01002836 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002837 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002838 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002839 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002840 printing_tcp->flags |= TCB_REPRINT;
2841 tprints(" <unfinished ...>\n");
2842 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002843 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002844 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002845 /* We assume that ptrace error was caused by process death.
2846 * We used to detach(tcp) here, but since we no longer
2847 * implement "detach before death" policy/hack,
2848 * we can let this process to report its death to us
2849 * normally, via WIFEXITED or WIFSIGNALED wait status.
2850 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002851 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002852 /* It's our real child (and we also trace it) */
2853 /* my_tkill(pid, SIGKILL); - why? */
2854 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002855 }
2856 continue;
2857 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002858 restart_tracee_with_sig_0:
2859 sig = 0;
2860 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002861 /* Remember current print column before continuing. */
2862 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002863 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002864 cleanup();
2865 return -1;
2866 }
2867 }
2868 return 0;
2869}
2870
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002871#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002872
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002873void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002874tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002875{
2876 va_list args;
2877
Andreas Schwabe5355de2009-10-27 16:56:43 +01002878 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002879 if (outf) {
2880 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002881 if (n < 0) {
2882 if (outf != stderr)
2883 perror(outfname == NULL
2884 ? "<writing to pipe>" : outfname);
2885 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002886 curcol += n;
2887 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002888 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002889}
2890
2891void
2892tprints(const char *str)
2893{
2894 if (outf) {
2895 int n = fputs(str, outf);
2896 if (n >= 0) {
2897 curcol += strlen(str);
2898 return;
2899 }
2900 if (outf != stderr)
2901 perror(outfname == NULL
2902 ? "<writing to pipe>" : outfname);
2903 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002904}
2905
2906void
Denys Vlasenko12014262011-05-30 14:00:14 +02002907printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002908{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002909 if (printing_tcp) {
2910 if (printing_tcp->ptrace_errno) {
2911 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002912 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002913 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002914 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002915 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002916 printing_tcp->ptrace_errno = 0;
2917 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2918 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002919 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002920 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002921 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002922
2923 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002924 curcol = 0;
2925 if ((followfork == 1 || pflag_seen > 1) && outfname)
2926 tprintf("%-5d ", tcp->pid);
2927 else if (nprocs > 1 && !outfname)
2928 tprintf("[pid %5u] ", tcp->pid);
2929 if (tflag) {
2930 char str[sizeof("HH:MM:SS")];
2931 struct timeval tv, dtv;
2932 static struct timeval otv;
2933
2934 gettimeofday(&tv, NULL);
2935 if (rflag) {
2936 if (otv.tv_sec == 0)
2937 otv = tv;
2938 tv_sub(&dtv, &tv, &otv);
2939 tprintf("%6ld.%06ld ",
2940 (long) dtv.tv_sec, (long) dtv.tv_usec);
2941 otv = tv;
2942 }
2943 else if (tflag > 2) {
2944 tprintf("%ld.%06ld ",
2945 (long) tv.tv_sec, (long) tv.tv_usec);
2946 }
2947 else {
2948 time_t local = tv.tv_sec;
2949 strftime(str, sizeof(str), "%T", localtime(&local));
2950 if (tflag > 1)
2951 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2952 else
2953 tprintf("%s ", str);
2954 }
2955 }
2956 if (iflag)
2957 printcall(tcp);
2958}
2959
2960void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002961tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002962{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002963 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002964 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002965}
2966
Wichert Akkermanea78f0f1999-11-29 15:34:02 +00002967#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002968
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002969int
2970mp_ioctl(int fd, int cmd, void *arg, int size)
2971{
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002972 struct iovec iov[2];
2973 int n = 1;
Roland McGrath553a6092002-12-16 20:40:39 +00002974
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002975 iov[0].iov_base = &cmd;
2976 iov[0].iov_len = sizeof cmd;
2977 if (arg) {
2978 ++n;
2979 iov[1].iov_base = arg;
2980 iov[1].iov_len = size;
2981 }
Roland McGrath553a6092002-12-16 20:40:39 +00002982
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002983 return writev(fd, iov, n);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002984}
2985
2986#endif