blob: 26cf91faf509c2e83f7fe58151ef1245d5ef55ee [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# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
Roland McGrath134813a2007-06-02 00:07:33 +000060
Denys Vlasenko84703742012-02-25 02:38:52 +010061#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062# include <asm/ptrace_offsets.h>
63#endif
64
Denys Vlasenko96d5a762008-12-29 19:13:27 +000065extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000066extern int optind;
67extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000068
Roland McGrath41c48222008-07-18 00:25:10 +000069int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020070unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020071/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020072static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000073int dtime = 0, xflag = 0, qflag = 0;
74cflag_t cflag = CFLAG_NONE;
Denys Vlasenkofd883382012-03-09 13:03:41 +010075static int iflag = 0, rflag = 0, tflag = 0;
76static int print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010077
78/* -I n */
79enum {
80 INTR_NOT_SET = 0,
81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85 NUM_INTR_OPTS
86};
87static int opt_intr;
88/* We play with signal mask only if this mode is active: */
89#define interactive (opt_intr == INTR_WHILE_WAIT)
90
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100105#ifdef USE_SEIZE
106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
107# define use_seize (post_attach_sigstop == 0)
108#else
109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
110# define use_seize 0
111#endif
112
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000113/* Sometimes we want to print only succeeding syscalls. */
114int not_failing_only = 0;
115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
117int show_fd_path = 0;
118
119/* are we filtering traces based on paths? */
120int tracing_paths = 0;
121
Dmitry V. Levina6809652008-11-10 17:14:58 +0000122static int exit_code = 0;
123static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200124static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700125
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static uid_t run_uid;
128static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200131static int acolumn = DEFAULT_ACOLUMN;
132static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000133static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200134static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100135struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100136static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200138static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200139static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100141static char *os_release; /* from uname() */
142
Denys Vlasenko4c196382012-01-04 15:11:09 +0100143static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static int trace(void);
145static void cleanup(void);
146static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147static sigset_t empty_set, blocked_set;
148
149#ifdef HAVE_SIG_ATOMIC_T
150static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100151#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200156usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157{
158 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100159usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
160 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100161 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100162 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100163 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200165-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100166-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100168-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100170-I interruptible\n\
171 1: no signals are blocked\n\
172 2: fatal signals are blocked while decoding syscall (default)\n\
173 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
174 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
175 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-q -- suppress messages about attaching, detaching, etc.\n\
177-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100178-T -- print time spent in each syscall\n\
179-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000181-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100182-h -- print help message\n\
183-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-a column -- alignment COLUMN for printing syscall results (default %d)\n\
185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
186 options: trace, abbrev, verbose, raw, signal, read, or write\n\
187-o file -- send trace output to FILE instead of stderr\n\
188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
189-p pid -- trace process with process id PID, may be repeated\n\
190-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
191-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
192-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000193-E var=val -- put var=val in the environment for command\n\
194-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000195-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000197-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198 */
199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 exit(exitval);
201}
202
Denys Vlasenko75422762011-05-27 14:36:01 +0200203static void die(void) __attribute__ ((noreturn));
204static void die(void)
205{
206 if (strace_tracer_pid == getpid()) {
207 cflag = 0;
208 cleanup();
209 }
210 exit(1);
211}
212
213static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200214{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100215 char *msg;
216
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000217 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100218
219 /* We want to print entire message with single fprintf to ensure
220 * message integrity if stderr is shared with other programs.
221 * Thus we use vasprintf + single fprintf.
222 */
223 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100224 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100225 if (err_no)
226 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
227 else
228 fprintf(stderr, "%s: %s\n", progname, msg);
229 free(msg);
230 } else {
231 /* malloc in vasprintf failed, try it without malloc */
232 fprintf(stderr, "%s: ", progname);
233 vfprintf(stderr, fmt, p);
234 if (err_no)
235 fprintf(stderr, ": %s\n", strerror(err_no));
236 else
237 putc('\n', stderr);
238 }
239 /* We don't switch stderr to buffered, thus fprintf(stderr)
240 * always flushes its output and this is not necessary: */
241 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200242}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243
Denys Vlasenko75422762011-05-27 14:36:01 +0200244void error_msg(const char *fmt, ...)
245{
246 va_list p;
247 va_start(p, fmt);
248 verror_msg(0, fmt, p);
249 va_end(p);
250}
251
252void error_msg_and_die(const char *fmt, ...)
253{
254 va_list p;
255 va_start(p, fmt);
256 verror_msg(0, fmt, p);
257 die();
258}
259
260void perror_msg(const char *fmt, ...)
261{
262 va_list p;
263 va_start(p, fmt);
264 verror_msg(errno, fmt, p);
265 va_end(p);
266}
267
268void perror_msg_and_die(const char *fmt, ...)
269{
270 va_list p;
271 va_start(p, fmt);
272 verror_msg(errno, fmt, p);
273 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200274}
275
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200276void die_out_of_memory(void)
277{
278 static bool recursed = 0;
279 if (recursed)
280 exit(1);
281 recursed = 1;
282 error_msg_and_die("Out of memory");
283}
284
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400285/* Glue for systems without a MMU that cannot provide fork() */
286#ifdef HAVE_FORK
287# define strace_vforked 0
288#else
289# define strace_vforked 1
290# define fork() vfork()
291#endif
292
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100293#ifdef USE_SEIZE
294static int
295ptrace_attach_or_seize(int pid)
296{
297 int r;
298 if (!use_seize)
299 return ptrace(PTRACE_ATTACH, pid, 0, 0);
300 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
301 if (r)
302 return r;
303 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
304 return r;
305}
306#else
307# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
308#endif
309
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200310static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311set_cloexec_flag(int fd)
312{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200313 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000314
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200315 flags = fcntl(fd, F_GETFD);
316 if (flags < 0) {
317 /* Can happen only if fd is bad.
318 * Should never happen: if it does, we have a bug
319 * in the caller. Therefore we just abort
320 * instead of propagating the error.
321 */
322 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000323 }
324
325 newflags = flags | FD_CLOEXEC;
326 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200327 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200329 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330}
331
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100332static void kill_save_errno(pid_t pid, int sig)
333{
334 int saved_errno = errno;
335
336 (void) kill(pid, sig);
337 errno = saved_errno;
338}
339
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000340/*
341 * When strace is setuid executable, we have to swap uids
342 * before and after filesystem and process management operations.
343 */
344static void
345swap_uid(void)
346{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000347 int euid = geteuid(), uid = getuid();
348
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200349 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200350 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000351 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000352}
353
Roland McGrath4bfa6262007-07-05 20:03:16 +0000354#if _LFS64_LARGEFILE
355# define fopen_for_output fopen64
356#else
357# define fopen_for_output fopen
358#endif
359
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000360static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200361strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000362{
363 FILE *fp;
364
365 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200366 fp = fopen_for_output(path, "w");
367 if (!fp)
368 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000369 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200370 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000371 return fp;
372}
373
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200374static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000375
376#ifndef _PATH_BSHELL
377# define _PATH_BSHELL "/bin/sh"
378#endif
379
380/*
381 * We cannot use standard popen(3) here because we have to distinguish
382 * popen child process from other processes we trace, and standard popen(3)
383 * does not export its child's pid.
384 */
385static FILE *
386strace_popen(const char *command)
387{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200388 FILE *fp;
389 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000390
391 swap_uid();
392 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200393 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000394
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200395 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000396
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200397 popen_pid = vfork();
398 if (popen_pid == -1)
399 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000400
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200401 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000402 /* child */
403 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200404 if (fds[0] != 0) {
405 if (dup2(fds[0], 0))
406 perror_msg_and_die("dup2");
407 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000408 }
409 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200410 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000411 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200412
413 /* parent */
414 close(fds[0]);
415 swap_uid();
416 fp = fdopen(fds[1], "w");
417 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200418 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200419 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000420}
421
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200422static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000423newoutf(struct tcb *tcp)
424{
425 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000426 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000427 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200428 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000429 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000430}
431
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100432static void process_opt_p_list(char *opt)
433{
434 while (*opt) {
435 /*
436 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
437 * pidof uses space as delim, pgrep uses newline. :(
438 */
439 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100440 char *delim = opt + strcspn(opt, ", \n\t");
441 char c = *delim;
442
443 *delim = '\0';
444 pid = atoi(opt); /* TODO: stricter parsing of the number? */
445 if (pid <= 0) {
446 error_msg("Invalid process id: '%s'", opt);
447 *delim = c;
448 return;
449 }
450 if (pid == strace_tracer_pid) {
451 error_msg("I'm sorry, I can't let you do that, Dave.");
452 *delim = c;
453 return;
454 }
455 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100456 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100457 if (c == '\0')
458 break;
459 opt = delim + 1;
460 }
461}
462
Roland McGrath02203312007-06-11 22:06:31 +0000463static void
464startup_attach(void)
465{
466 int tcbi;
467 struct tcb *tcp;
468
469 /*
470 * Block user interruptions as we would leave the traced
471 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200472 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200473 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000474 */
475 if (interactive)
476 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
477
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000478 if (daemonized_tracer) {
479 pid_t pid = fork();
480 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200481 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000482 }
483 if (pid) { /* parent */
484 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200485 * Wait for grandchild to attach to straced process
486 * (grandparent). Grandchild SIGKILLs us after it attached.
487 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000488 * it proceeds to exec the straced program.
489 */
490 pause();
491 _exit(0); /* paranoia */
492 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200493 /* grandchild */
494 /* We will be the tracer process. Remember our new pid: */
495 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000496 }
497
Roland McGrath02203312007-06-11 22:06:31 +0000498 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
499 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200500
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100501 if (!(tcp->flags & TCB_INUSE))
502 continue;
503
Denys Vlasenkod116a732011-09-05 14:01:33 +0200504 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100505 if (tcp->flags & TCB_ATTACHED)
506 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200507
508 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000509 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200510 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000511
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 Vlasenko75fe85c2012-03-09 15:15:24 +0100564 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200565 /* -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 Vlasenko31fa8a22012-01-29 02:01:44 +0100574 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000575 perror("attach: ptrace(PTRACE_ATTACH, ...)");
576 droptcb(tcp);
577 continue;
578 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100579 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200580 if (debug)
581 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000582
583 if (daemonized_tracer) {
584 /*
585 * It is our grandparent we trace, not a -p PID.
586 * Don't want to just detach on exit, so...
587 */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100588 tcp->flags |= TCB_STRACE_CHILD;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000589 /*
590 * Make parent go away.
591 * Also makes grandparent's wait() unblock.
592 */
593 kill(getppid(), SIGKILL);
594 }
595
Roland McGrath02203312007-06-11 22:06:31 +0000596 if (!qflag)
597 fprintf(stderr,
598 "Process %u attached - interrupt to quit\n",
599 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200600 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000601
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200602 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000603 if (interactive)
604 sigprocmask(SIG_SETMASK, &empty_set, NULL);
605}
606
607static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200608startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000609{
610 struct stat statbuf;
611 const char *filename;
612 char pathname[MAXPATHLEN];
613 int pid = 0;
614 struct tcb *tcp;
615
616 filename = argv[0];
617 if (strchr(filename, '/')) {
618 if (strlen(filename) > sizeof pathname - 1) {
619 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200620 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000621 }
622 strcpy(pathname, filename);
623 }
624#ifdef USE_DEBUGGING_EXEC
625 /*
626 * Debuggers customarily check the current directory
627 * first regardless of the path but doing that gives
628 * security geeks a panic attack.
629 */
630 else if (stat(filename, &statbuf) == 0)
631 strcpy(pathname, filename);
632#endif /* USE_DEBUGGING_EXEC */
633 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000634 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000635 int m, n, len;
636
637 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100638 const char *colon = strchr(path, ':');
639 if (colon) {
640 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000641 m = n + 1;
642 }
643 else
644 m = n = strlen(path);
645 if (n == 0) {
646 if (!getcwd(pathname, MAXPATHLEN))
647 continue;
648 len = strlen(pathname);
649 }
650 else if (n > sizeof pathname - 1)
651 continue;
652 else {
653 strncpy(pathname, path, n);
654 len = n;
655 }
656 if (len && pathname[len - 1] != '/')
657 pathname[len++] = '/';
658 strcpy(pathname + len, filename);
659 if (stat(pathname, &statbuf) == 0 &&
660 /* Accept only regular files
661 with some execute bits set.
662 XXX not perfect, might still fail */
663 S_ISREG(statbuf.st_mode) &&
664 (statbuf.st_mode & 0111))
665 break;
666 }
667 }
668 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200669 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000670 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000671 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000672 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200673 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000674 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200675 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
676 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000677 ) {
678 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200679 if (outf != stderr)
680 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100681 if (!daemonized_tracer && !use_seize) {
682 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200683 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000684 }
Roland McGrath02203312007-06-11 22:06:31 +0000685 }
Roland McGrath02203312007-06-11 22:06:31 +0000686
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200687 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000688 uid_t run_euid = run_uid;
689 gid_t run_egid = run_gid;
690
691 if (statbuf.st_mode & S_ISUID)
692 run_euid = statbuf.st_uid;
693 if (statbuf.st_mode & S_ISGID)
694 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000695 /*
696 * It is important to set groups before we
697 * lose privileges on setuid.
698 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200699 if (initgroups(username, run_gid) < 0) {
700 perror_msg_and_die("initgroups");
701 }
702 if (setregid(run_gid, run_egid) < 0) {
703 perror_msg_and_die("setregid");
704 }
705 if (setreuid(run_uid, run_euid) < 0) {
706 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000707 }
708 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200709 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000710 setreuid(run_uid, run_uid);
711
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000712 if (!daemonized_tracer) {
713 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200714 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000715 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200716 * the immediately following execve syscall.
717 * Can't do this on NOMMU systems, we are after
718 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000719 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400720 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200721 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000722 } else {
723 struct sigaction sv_sigchld;
724 sigaction(SIGCHLD, NULL, &sv_sigchld);
725 /*
726 * Make sure it is not SIG_IGN, otherwise wait
727 * will not block.
728 */
729 signal(SIGCHLD, SIG_DFL);
730 /*
731 * Wait for grandchild to attach to us.
732 * It kills child after that, and wait() unblocks.
733 */
734 alarm(3);
735 wait(NULL);
736 alarm(0);
737 sigaction(SIGCHLD, &sv_sigchld, NULL);
738 }
Roland McGrath02203312007-06-11 22:06:31 +0000739
740 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200741 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000742 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000743
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200744 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200745
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200746 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100747 if (!use_seize) {
748 /* child did PTRACE_TRACEME, nothing to do in parent */
749 } else {
750 if (!strace_vforked) {
751 /* Wait until child stopped itself */
752 int status;
753 while (waitpid(pid, &status, WSTOPPED) < 0) {
754 if (errno == EINTR)
755 continue;
756 perror_msg_and_die("waitpid");
757 }
758 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100759 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100760 perror_msg_and_die("Unexpected wait status %x", status);
761 }
762 }
763 /* Else: vforked case, we have no way to sync.
764 * Just attach to it as soon as possible.
765 * This means that we may miss a few first syscalls...
766 */
767
768 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100769 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100770 perror_msg_and_die("Can't attach to %d", pid);
771 }
772 if (!strace_vforked)
773 kill(pid, SIGCONT);
774 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200775 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200776 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100777 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200778 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100779 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200780 }
781 else {
782 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
783 strace_tracer_pid = getpid();
784 /* The tracee is our parent: */
785 pid = getppid();
786 tcp = alloctcb(pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000787 }
Roland McGrath02203312007-06-11 22:06:31 +0000788}
789
Wang Chaob13c0de2010-11-12 17:25:19 +0800790/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000791 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800792 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000793 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800794 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000795static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200796test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800797{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000798 int pid, expected_grandchild = 0, found_grandchild = 0;
799 const unsigned int test_options = PTRACE_O_TRACECLONE |
800 PTRACE_O_TRACEFORK |
801 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800802
Denys Vlasenko5d645812011-08-20 12:48:18 +0200803 pid = fork();
804 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000805 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200806 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000807 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100808 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000809 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
810 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100811 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000812 if (fork() < 0)
813 perror_msg_and_die("fork");
814 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800815 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000816
817 while (1) {
818 int status, tracee_pid;
819
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000820 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000821 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000822 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000823 if (errno == EINTR)
824 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100825 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000826 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000827 kill_save_errno(pid, SIGKILL);
828 perror_msg_and_die("%s: unexpected wait result %d",
829 __func__, tracee_pid);
830 }
831 if (WIFEXITED(status)) {
832 if (WEXITSTATUS(status)) {
833 if (tracee_pid != pid)
834 kill_save_errno(pid, SIGKILL);
835 error_msg_and_die("%s: unexpected exit status %u",
836 __func__, WEXITSTATUS(status));
837 }
838 continue;
839 }
840 if (WIFSIGNALED(status)) {
841 if (tracee_pid != pid)
842 kill_save_errno(pid, SIGKILL);
843 error_msg_and_die("%s: unexpected signal %u",
844 __func__, WTERMSIG(status));
845 }
846 if (!WIFSTOPPED(status)) {
847 if (tracee_pid != pid)
848 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100849 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000850 error_msg_and_die("%s: unexpected wait status %x",
851 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000852 }
853 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000854 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000855 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
856 kill_save_errno(tracee_pid, SIGKILL);
857 kill_save_errno(pid, SIGKILL);
858 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800859 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000860 continue;
861 }
862 switch (WSTOPSIG(status)) {
863 case SIGSTOP:
864 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
865 && errno != EINVAL && errno != EIO)
866 perror_msg("PTRACE_SETOPTIONS");
867 break;
868 case SIGTRAP:
869 if (status >> 16 == PTRACE_EVENT_FORK) {
870 long msg = 0;
871
872 if (ptrace(PTRACE_GETEVENTMSG, pid,
873 NULL, (long) &msg) == 0)
874 expected_grandchild = msg;
875 }
876 break;
877 }
878 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
879 kill_save_errno(pid, SIGKILL);
880 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800881 }
882 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000883 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200884 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000885 if (debug)
886 fprintf(stderr, "ptrace_setoptions = %#x\n",
887 ptrace_setoptions);
888 return;
889 }
890 error_msg("Test for PTRACE_O_TRACECLONE failed, "
891 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800892}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200893
894/*
895 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
896 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
897 * and then see whether it will stop with (SIGTRAP | 0x80).
898 *
899 * Use of this option enables correct handling of user-generated SIGTRAPs,
900 * and SIGTRAPs generated by special instructions such as int3 on x86:
901 * _start: .globl _start
902 * int3
903 * movl $42, %ebx
904 * movl $1, %eax
905 * int $0x80
906 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
907 */
908static void
909test_ptrace_setoptions_for_all(void)
910{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000911 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
912 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200913 int pid;
914 int it_worked = 0;
915
916 pid = fork();
917 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200918 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200919
920 if (pid == 0) {
921 pid = getpid();
922 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +0200923 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000924 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
925 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200926 kill(pid, SIGSTOP);
927 _exit(0); /* parent should see entry into this syscall */
928 }
929
930 while (1) {
931 int status, tracee_pid;
932
933 errno = 0;
934 tracee_pid = wait(&status);
935 if (tracee_pid <= 0) {
936 if (errno == EINTR)
937 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000938 kill_save_errno(pid, SIGKILL);
939 perror_msg_and_die("%s: unexpected wait result %d",
940 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200941 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200942 if (WIFEXITED(status)) {
943 if (WEXITSTATUS(status) == 0)
944 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000945 error_msg_and_die("%s: unexpected exit status %u",
946 __func__, WEXITSTATUS(status));
947 }
948 if (WIFSIGNALED(status)) {
949 error_msg_and_die("%s: unexpected signal %u",
950 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +0200951 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200952 if (!WIFSTOPPED(status)) {
953 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000954 error_msg_and_die("%s: unexpected wait status %x",
955 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200956 }
957 if (WSTOPSIG(status) == SIGSTOP) {
958 /*
959 * We don't check "options aren't accepted" error.
960 * If it happens, we'll never get (SIGTRAP | 0x80),
961 * and thus will decide to not use the option.
962 * IOW: the outcome of the test will be correct.
963 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000964 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
965 && errno != EINVAL && errno != EIO)
966 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200967 }
968 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
969 it_worked = 1;
970 }
971 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000972 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +0200973 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200974 }
975 }
976
977 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +0200978 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200979 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200980 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200981 fprintf(stderr, "ptrace_setoptions = %#x\n",
982 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200983 return;
984 }
985
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000986 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
987 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200988}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100989
990# ifdef USE_SEIZE
991static void
992test_ptrace_seize(void)
993{
994 int pid;
995
996 pid = fork();
997 if (pid < 0)
998 perror_msg_and_die("fork");
999
1000 if (pid == 0) {
1001 pause();
1002 _exit(0);
1003 }
1004
1005 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1006 * attaching tracee continues to run unless a trap condition occurs.
1007 * PTRACE_SEIZE doesn't affect signal or group stop state.
1008 */
1009 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1010 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1011 } else if (debug) {
1012 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1013 }
1014
1015 kill(pid, SIGKILL);
1016
1017 while (1) {
1018 int status, tracee_pid;
1019
1020 errno = 0;
1021 tracee_pid = waitpid(pid, &status, 0);
1022 if (tracee_pid <= 0) {
1023 if (errno == EINTR)
1024 continue;
1025 perror_msg_and_die("%s: unexpected wait result %d",
1026 __func__, tracee_pid);
1027 }
1028 if (WIFSIGNALED(status)) {
1029 return;
1030 }
1031 error_msg_and_die("%s: unexpected wait status %x",
1032 __func__, status);
1033 }
1034}
1035# else /* !USE_SEIZE */
1036# define test_ptrace_seize() ((void)0)
1037# endif
1038
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001039/* Noinline: don't want main to have struct utsname permanently on stack */
1040static void __attribute__ ((noinline))
1041get_os_release(void)
1042{
1043 struct utsname u;
1044 if (uname(&u) < 0)
1045 perror_msg_and_die("uname");
1046 os_release = strdup(u.release);
1047 if (!os_release)
1048 die_out_of_memory();
1049}
1050
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001052main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001055 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001056 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 struct sigaction sa;
1058
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001059 progname = argv[0] ? argv[0] : "strace";
1060
Denys Vlasenko75422762011-05-27 14:36:01 +02001061 strace_tracer_pid = getpid();
1062
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001063 get_os_release();
1064
Roland McGrathee9d4352002-12-18 04:16:10 +00001065 /* Allocate the initial tcbtab. */
1066 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001067 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001068 if (!tcbtab)
1069 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001070 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001071 if (!tcp)
1072 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001073 for (c = 0; c < tcbtabsize; c++)
1074 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001075
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001077 set_sortby(DEFAULT_SORTBY);
1078 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 qualify("trace=all");
1080 qualify("abbrev=all");
1081 qualify("verbose=all");
1082 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001084 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001085 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001086 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 switch (c) {
1088 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001089 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001090 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001091 }
1092 cflag = CFLAG_ONLY_STATS;
1093 break;
1094 case 'C':
1095 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001096 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001097 }
1098 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 break;
1100 case 'd':
1101 debug++;
1102 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001103 case 'D':
1104 daemonized_tracer = 1;
1105 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001106 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001107 optF = 1;
1108 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109 case 'f':
1110 followfork++;
1111 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 case 'h':
1113 usage(stdout, 0);
1114 break;
1115 case 'i':
1116 iflag++;
1117 break;
1118 case 'q':
1119 qflag++;
1120 break;
1121 case 'r':
1122 rflag++;
1123 tflag++;
1124 break;
1125 case 't':
1126 tflag++;
1127 break;
1128 case 'T':
1129 dtime++;
1130 break;
1131 case 'x':
1132 xflag++;
1133 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001134 case 'y':
1135 show_fd_path = 1;
1136 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 case 'v':
1138 qualify("abbrev=none");
1139 break;
1140 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001141 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 exit(0);
1143 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001144 case 'z':
1145 not_failing_only = 1;
1146 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 case 'a':
1148 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001149 if (acolumn < 0)
1150 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 break;
1152 case 'e':
1153 qualify(optarg);
1154 break;
1155 case 'o':
1156 outfname = strdup(optarg);
1157 break;
1158 case 'O':
1159 set_overhead(atoi(optarg));
1160 break;
1161 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001162 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001164 case 'P':
1165 tracing_paths = 1;
1166 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001167 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001168 }
1169 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 case 's':
1171 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001172 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001173 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001174 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 break;
1176 case 'S':
1177 set_sortby(optarg);
1178 break;
1179 case 'u':
1180 username = strdup(optarg);
1181 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001182 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001183 if (putenv(optarg) < 0)
1184 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001185 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001186 case 'I':
1187 opt_intr = atoi(optarg);
1188 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1189 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1190 }
1191 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192 default:
1193 usage(stderr, 1);
1194 break;
1195 }
1196 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001197 argv += optind;
1198 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199
Denys Vlasenko102ec492011-08-25 01:27:59 +02001200 acolumn_spaces = malloc(acolumn + 1);
1201 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001202 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001203 memset(acolumn_spaces, ' ', acolumn);
1204 acolumn_spaces[acolumn] = '\0';
1205
Denys Vlasenko837399a2012-01-24 11:37:03 +01001206 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001207 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001208 usage(stderr, 1);
1209
Denys Vlasenkofd883382012-03-09 13:03:41 +01001210 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001211 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001212 }
1213
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001214 if (!followfork)
1215 followfork = optF;
1216
Roland McGrathcb9def62006-04-25 07:48:03 +00001217 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001218 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001219 }
1220
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 /* See if they want to run as another user. */
1222 if (username != NULL) {
1223 struct passwd *pent;
1224
1225 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001226 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001228 pent = getpwnam(username);
1229 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001230 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 }
1232 run_uid = pent->pw_uid;
1233 run_gid = pent->pw_gid;
1234 }
1235 else {
1236 run_uid = getuid();
1237 run_gid = getgid();
1238 }
1239
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001240 if (followfork)
1241 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001242 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001243 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001244
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 /* Check if they want to redirect the output. */
1246 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001247 /* See if they want to pipe the output. */
1248 if (outfname[0] == '|' || outfname[0] == '!') {
1249 /*
1250 * We can't do the <outfname>.PID funny business
1251 * when using popen, so prohibit it.
1252 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001253 if (followfork > 1)
1254 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1255 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001256 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001257 else if (followfork <= 1)
1258 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001259 }
1260
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001261 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001262 char *buf = malloc(BUFSIZ);
1263 if (!buf)
1264 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001265 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001266 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001267 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001268 if (!opt_intr)
1269 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001271 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001272 if (!opt_intr)
1273 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001274
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001275 /* argv[0] -pPID -oFILE Default interactive setting
1276 * yes 0 0 INTR_WHILE_WAIT
1277 * no 1 0 INTR_WHILE_WAIT
1278 * yes 0 1 INTR_NEVER
1279 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001280 */
1281
1282 /* STARTUP_CHILD must be called before the signal handlers get
1283 installed below as they are inherited into the spawned process.
1284 Also we do not need to be protected by them as during interruption
1285 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001286 if (argv[0])
1287 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289 sigemptyset(&empty_set);
1290 sigemptyset(&blocked_set);
1291 sa.sa_handler = SIG_IGN;
1292 sigemptyset(&sa.sa_mask);
1293 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001294 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1295 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1296 if (opt_intr != INTR_ANYWHERE) {
1297 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1298 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1299 /*
1300 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1301 * fatal signals are blocked while syscall stop is processed,
1302 * and acted on in between, when waiting for new syscall stops.
1303 * In non-interactive mode, signals are ignored.
1304 */
1305 if (opt_intr == INTR_WHILE_WAIT) {
1306 sigaddset(&blocked_set, SIGHUP);
1307 sigaddset(&blocked_set, SIGINT);
1308 sigaddset(&blocked_set, SIGQUIT);
1309 sigaddset(&blocked_set, SIGPIPE);
1310 sigaddset(&blocked_set, SIGTERM);
1311 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001312 }
1313 /* SIG_IGN, or set handler for these */
1314 sigaction(SIGHUP, &sa, NULL);
1315 sigaction(SIGINT, &sa, NULL);
1316 sigaction(SIGQUIT, &sa, NULL);
1317 sigaction(SIGPIPE, &sa, NULL);
1318 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 }
Roland McGrath553a6092002-12-16 20:40:39 +00001320 /* Make sure SIGCHLD has the default action so that waitpid
1321 definitely works without losing track of children. The user
1322 should not have given us a bogus state to inherit, but he might
1323 have. Arguably we should detect SIG_IGN here and pass it on
1324 to children, but probably noone really needs that. */
1325 sa.sa_handler = SIG_DFL;
1326 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327
Denys Vlasenkofd883382012-03-09 13:03:41 +01001328 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001329 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001330
Denys Vlasenkofd883382012-03-09 13:03:41 +01001331 /* Do we want pids printed in our -o OUTFILE?
1332 * -ff: no (every pid has its own file); or
1333 * -f: yes (there can be more pids in the future); or
1334 * -p PID1,PID2: yes (there are already more than one pid)
1335 */
1336 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
1337
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338 if (trace() < 0)
1339 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001340
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001342 fflush(NULL);
1343 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001344 /* Avoid potential core file clobbering. */
1345 struct rlimit rlim = {0, 0};
1346 setrlimit(RLIMIT_CORE, &rlim);
1347
Dmitry V. Levina6809652008-11-10 17:14:58 +00001348 /* Child was killed by a signal, mimic that. */
1349 exit_code &= 0xff;
1350 signal(exit_code, SIG_DFL);
1351 raise(exit_code);
1352 /* Paranoia - what if this signal is not fatal?
1353 Exit with 128 + signo then. */
1354 exit_code += 128;
1355 }
1356 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357}
1358
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001359static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001360expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001361{
1362 /* Allocate some more TCBs and expand the table.
1363 We don't want to relocate the TCBs because our
1364 callers have pointers and it would be a pain.
1365 So tcbtab is a table of pointers. Since we never
1366 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001367 int i = tcbtabsize;
1368 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1369 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001370 if (!newtab || !newtcbs)
1371 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001372 tcbtabsize *= 2;
1373 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001374 while (i < tcbtabsize)
1375 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001376}
1377
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001379alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380{
1381 int i;
1382 struct tcb *tcp;
1383
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001384 if (nprocs == tcbtabsize)
1385 expand_tcbtab();
1386
Roland McGrathee9d4352002-12-18 04:16:10 +00001387 for (i = 0; i < tcbtabsize; i++) {
1388 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001390 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001392 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001394#if SUPPORTED_PERSONALITIES > 1
1395 tcp->currpers = current_personality;
1396#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001397 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001398 if (debug)
1399 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001400 if (command_options_parsed)
1401 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402 return tcp;
1403 }
1404 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001405 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406}
1407
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001408static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001409pid2tcb(int pid)
1410{
1411 int i;
1412
1413 if (pid <= 0)
1414 return NULL;
1415
1416 for (i = 0; i < tcbtabsize; i++) {
1417 struct tcb *tcp = tcbtab[i];
1418 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1419 return tcp;
1420 }
1421
1422 return NULL;
1423}
1424
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425void
Denys Vlasenko12014262011-05-30 14:00:14 +02001426droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427{
1428 if (tcp->pid == 0)
1429 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001430
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001431 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001432 if (debug)
1433 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001434
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001435 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001437
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001438 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439}
1440
Roland McGrath0a463882007-07-05 18:43:16 +00001441/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001442 * Never call DETACH twice on the same process as both unattached and
1443 * attached-unstopped processes give the same ESRCH. For unattached process we
1444 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1445 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001447detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001448{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001449 int error;
1450 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451
1452 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001453 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455 /*
1456 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001457 * before detaching. Arghh. We go through hoops
1458 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001460#if defined(SPARC)
1461#undef PTRACE_DETACH
1462#define PTRACE_DETACH PTRACE_SUNDETACH
1463#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001464
1465 sigstop_expected = 0;
1466 if (tcp->flags & TCB_ATTACHED) {
1467 /*
1468 * We attached but possibly didn't see the expected SIGSTOP.
1469 * We must catch exactly one as otherwise the detached process
1470 * would be left stopped (process state T).
1471 */
1472 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1473 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1474 if (error == 0) {
1475 /* On a clear day, you can see forever. */
1476 }
1477 else if (errno != ESRCH) {
1478 /* Shouldn't happen. */
1479 perror("detach: ptrace(PTRACE_DETACH, ...)");
1480 }
1481 else if (my_tkill(tcp->pid, 0) < 0) {
1482 if (errno != ESRCH)
1483 perror("detach: checking sanity");
1484 }
1485 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1486 if (errno != ESRCH)
1487 perror("detach: stopping child");
1488 }
1489 else
1490 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001491 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001492
1493 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001495#ifdef __WALL
1496 if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
1497 if (errno == ECHILD) /* Already gone. */
1498 break;
1499 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001500 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001501 break;
1502 }
1503#endif /* __WALL */
1504 /* No __WALL here. */
1505 if (waitpid(tcp->pid, &status, 0) < 0) {
1506 if (errno != ECHILD) {
1507 perror("detach: waiting");
1508 break;
1509 }
1510#ifdef __WCLONE
1511 /* If no processes, try clones. */
1512 if (wait4(tcp->pid, &status, __WCLONE,
1513 NULL) < 0) {
1514 if (errno != ECHILD)
1515 perror("detach: waiting");
1516 break;
1517 }
1518#endif /* __WCLONE */
1519 }
1520#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001521 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001522#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 if (!WIFSTOPPED(status)) {
1524 /* Au revoir, mon ami. */
1525 break;
1526 }
1527 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001528 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529 break;
1530 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001531 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001532 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001533 : WSTOPSIG(status));
1534 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001537 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001539 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 fprintf(stderr, "Process %u detached\n", tcp->pid);
1541
1542 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001543
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544 return error;
1545}
1546
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001548cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549{
1550 int i;
1551 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001552 int fatal_sig;
1553
1554 /* 'interrupted' is a volatile object, fetch it only once */
1555 fatal_sig = interrupted;
1556 if (!fatal_sig)
1557 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001558
Roland McGrathee9d4352002-12-18 04:16:10 +00001559 for (i = 0; i < tcbtabsize; i++) {
1560 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 if (!(tcp->flags & TCB_INUSE))
1562 continue;
1563 if (debug)
1564 fprintf(stderr,
1565 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001566 if (printing_tcp &&
1567 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1568 tprints(" <unfinished ...>\n");
1569 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001571 if (!(tcp->flags & TCB_STRACE_CHILD))
Denys Vlasenko4c196382012-01-04 15:11:09 +01001572 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573 else {
1574 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001575 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001576 }
1577 }
1578 if (cflag)
1579 call_summary(outf);
1580}
1581
1582static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001583interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001585 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586}
1587
1588#ifndef HAVE_STRERROR
1589
Roland McGrath6d2b3492002-12-30 00:51:30 +00001590#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591extern int sys_nerr;
1592extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001593#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594
1595const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001596strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001598 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001600 if (err_no < 1 || err_no >= sys_nerr) {
1601 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602 return buf;
1603 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001604 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605}
1606
1607#endif /* HAVE_STERRROR */
1608
1609#ifndef HAVE_STRSIGNAL
1610
Roland McGrath8f474e02003-01-14 07:53:33 +00001611#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001612extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001614#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1615extern char *_sys_siglist[];
1616#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617
1618const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001619strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001621 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622
1623 if (sig < 1 || sig >= NSIG) {
1624 sprintf(buf, "Unknown signal %d", sig);
1625 return buf;
1626 }
1627#ifdef HAVE__SYS_SIGLIST
1628 return _sys_siglist[sig];
1629#else
1630 return sys_siglist[sig];
1631#endif
1632}
1633
1634#endif /* HAVE_STRSIGNAL */
1635
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001637trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001640 struct rusage *rup = cflag ? &ru : NULL;
1641# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001642 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001643# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644
Roland McGratheb9e2e82009-06-02 16:49:22 -07001645 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001646 int pid;
1647 int wait_errno;
1648 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001649 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001650 struct tcb *tcp;
1651 unsigned event;
1652
Denys Vlasenko222713a2009-03-17 14:29:59 +00001653 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001654 return 0;
1655 if (interactive)
1656 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001657# ifdef __WALL
1658 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001659 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001660 /* this kernel does not support __WALL */
1661 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001662 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001663 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001664 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001665 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001666 pid = wait4(-1, &status, __WCLONE, rup);
1667 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001668 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001669 }
1670 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001671# else
1672 pid = wait4(-1, &status, 0, rup);
1673# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001675 if (interactive)
1676 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001678 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001679 switch (wait_errno) {
1680 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001682 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683 /*
1684 * We would like to verify this case
1685 * but sometimes a race in Solbourne's
1686 * version of SunOS sometimes reports
1687 * ECHILD before sending us SIGCHILD.
1688 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001689 return 0;
1690 default:
1691 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001692 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001693 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 }
1695 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001696 if (pid == popen_pid) {
1697 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001698 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001699 continue;
1700 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001701
1702 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001703 if (debug) {
1704 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001705 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001706 static const char *const event_names[] = {
1707 [PTRACE_EVENT_CLONE] = "CLONE",
1708 [PTRACE_EVENT_FORK] = "FORK",
1709 [PTRACE_EVENT_VFORK] = "VFORK",
1710 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1711 [PTRACE_EVENT_EXEC] = "EXEC",
1712 [PTRACE_EVENT_EXIT] = "EXIT",
1713 };
1714 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001715 if (event < ARRAY_SIZE(event_names))
1716 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001717 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001718 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001719 e = buf;
1720 }
1721 fprintf(stderr, " PTRACE_EVENT_%s", e);
1722 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001723 strcpy(buf, "???");
1724 if (WIFSIGNALED(status))
1725#ifdef WCOREDUMP
1726 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1727 WCOREDUMP(status) ? "core," : "",
1728 signame(WTERMSIG(status)));
1729#else
1730 sprintf(buf, "WIFSIGNALED,sig=%s",
1731 signame(WTERMSIG(status)));
1732#endif
1733 if (WIFEXITED(status))
1734 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1735 if (WIFSTOPPED(status))
1736 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001737#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001738 if (WIFCONTINUED(status))
1739 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001740#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001741 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1742 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001744 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001745 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001746
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001747 /* Under Linux, execve changes pid to thread leader's pid,
1748 * and we see this changed pid on EVENT_EXEC and later,
1749 * execve sysexit. Leader "disappears" without exit
1750 * notification. Let user know that, drop leader's tcb,
1751 * and fix up pid in execve thread's tcb.
1752 * Effectively, execve thread's tcb replaces leader's tcb.
1753 *
1754 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1755 * on exit syscall) in multithreaded programs exactly
1756 * in order to handle this case.
1757 *
1758 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1759 * On 2.6 and earlier, it can return garbage.
1760 */
1761 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1762 long old_pid = 0;
1763 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1764 && old_pid > 0
1765 && old_pid != pid
1766 ) {
1767 struct tcb *execve_thread = pid2tcb(old_pid);
1768 if (tcp) {
1769 outf = tcp->outf;
1770 curcol = tcp->curcol;
1771 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001772 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001773 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001774 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001775 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1776 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001777 fflush(outf);
1778 }
1779 if (execve_thread) {
1780 /* swap output FILEs (needed for -ff) */
1781 tcp->outf = execve_thread->outf;
1782 execve_thread->outf = outf;
1783 }
1784 droptcb(tcp);
1785 }
1786 tcp = execve_thread;
1787 if (tcp) {
1788 tcp->pid = pid;
1789 tcp->flags |= TCB_REPRINT;
1790 }
1791 }
1792 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001793
Denys Vlasenko5d645812011-08-20 12:48:18 +02001794 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001795 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001796 /* This is needed to go with the CLONE_PTRACE
1797 changes in process.c/util.c: we might see
1798 the child's initial trap before we see the
1799 parent return from the clone syscall.
1800 Leave the child suspended until the parent
1801 returns from its system call. Only then
1802 will we have the association of parent and
1803 child so that we know how to do clearbpt
1804 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001805 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001806 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001807 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001808 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001809 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001810 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001811 else
1812 /* This can happen if a clone call used
1813 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001814 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001815 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001816 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001817 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001818 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001819 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001820 /* set current output file */
1821 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001822 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001823 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1825 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001826 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001827
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001829 if (pid == strace_child)
1830 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001831 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1833 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001834#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001835 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001836 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001837 WCOREDUMP(status) ? "(core dumped) " : "");
1838#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001839 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001840 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001841#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001842 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001843 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001844 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001845 droptcb(tcp);
1846 continue;
1847 }
1848 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001849 if (pid == strace_child)
1850 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001851 if (tcp == printing_tcp) {
1852 tprints(" <unfinished ...>\n");
1853 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001854 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001855 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1856 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001857 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1858 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001859 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001860 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001861 droptcb(tcp);
1862 continue;
1863 }
1864 if (!WIFSTOPPED(status)) {
1865 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1866 droptcb(tcp);
1867 continue;
1868 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001869
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001870 /* Is this the very first time we see this tracee stopped? */
1871 if (tcp->flags & TCB_STARTUP) {
1872 if (debug)
1873 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001874 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001876 /*
1877 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001878 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001879 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001880 if (clearbpt(tcp) < 0) {
1881 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001882 droptcb(tcp);
1883 cleanup();
1884 return -1;
1885 }
1886 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001887 if (ptrace_setoptions) {
1888 if (debug)
1889 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1890 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1891 if (errno != ESRCH) {
1892 /* Should never happen, really */
1893 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001894 }
1895 }
1896 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001897 }
1898
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001899 sig = WSTOPSIG(status);
1900
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001901 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001902 /* Ptrace event */
1903#ifdef USE_SEIZE
1904 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001905 /*
1906 * PTRACE_INTERRUPT-stop or group-stop.
1907 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1908 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001909 if (sig == SIGSTOP
1910 || sig == SIGTSTP
1911 || sig == SIGTTIN
1912 || sig == SIGTTOU
1913 ) {
1914 stopped = 1;
1915 goto show_stopsig;
1916 }
1917 }
1918#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001919 goto restart_tracee_with_sig_0;
1920 }
1921
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001922 /* Is this post-attach SIGSTOP?
1923 * Interestingly, the process may stop
1924 * with STOPSIG equal to some other signal
1925 * than SIGSTOP if we happend to attach
1926 * just before the process takes a signal.
1927 */
1928 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
1929 if (debug)
1930 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
1931 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001932 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933 }
1934
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001935 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001936 siginfo_t si;
1937
1938 /* Nonzero (true) if tracee is stopped by signal
1939 * (as opposed to "tracee received signal").
1940 */
1941 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01001942#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001943 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01001944#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001945 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001946 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00001947#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001948 long pc = 0;
1949 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001950
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001951 upeek(tcp, PT_CR_IPSR, &psr);
1952 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001953
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001954# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001955 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001956# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001957# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001958#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001959# define PC_FORMAT_STR ""
1960# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001961#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001963 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001964 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001965 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01001966 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001967 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001968 PC_FORMAT_ARG);
1969 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001970 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001971 strsignal(sig),
1972 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00001973 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001974 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001975 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001976 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001977
1978 if (!stopped)
1979 /* It's signal-delivery-stop. Inject the signal */
1980 goto restart_tracee;
1981
1982 /* It's group-stop */
1983#ifdef USE_SEIZE
1984 if (use_seize) {
1985 /*
1986 * This ends ptrace-stop, but does *not* end group-stop.
1987 * This makes stopping signals work properly on straced process
1988 * (that is, process really stops. It used to continue to run).
1989 */
1990 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
1991 cleanup();
1992 return -1;
1993 }
1994 continue;
1995 }
1996 /* We don't have PTRACE_LISTEN support... */
1997#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001998 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001999 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002000
2001 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002002 if (interrupted)
2003 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002004
2005 /* This should be syscall entry or exit.
2006 * (Or it still can be that pesky post-execve SIGTRAP!)
2007 * Handle it.
2008 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002009 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2010 /* ptrace() failed in trace_syscall() with ESRCH.
2011 * Likely a result of process disappearing mid-flight.
2012 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002013 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002014 */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01002015 if (!(tcp->flags & TCB_STRACE_CHILD)) {
2016//TODO: why do we handle our child differently??
Denys Vlasenko000b6012012-01-28 01:25:03 +01002017 if (printing_tcp) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07002018 /* Do we have dangling line "syscall(param, param"?
Denys Vlasenko178de002011-06-24 22:54:25 +02002019 * Finish the line then.
Roland McGratheb9e2e82009-06-02 16:49:22 -07002020 */
Denys Vlasenko000b6012012-01-28 01:25:03 +01002021 printing_tcp->flags |= TCB_REPRINT;
2022 tprints(" <unfinished ...>\n");
2023 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002024 fflush(tcp->outf);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002025 }
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002026 /* We assume that ptrace error was caused by process death.
2027 * We used to detach(tcp) here, but since we no longer
2028 * implement "detach before death" policy/hack,
2029 * we can let this process to report its death to us
2030 * normally, via WIFEXITED or WIFSIGNALED wait status.
2031 */
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002032 } else {
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002033 /* It's our real child (and we also trace it) */
2034 /* my_tkill(pid, SIGKILL); - why? */
2035 /* droptcb(tcp); - why? */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002036 }
2037 continue;
2038 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002039 restart_tracee_with_sig_0:
2040 sig = 0;
2041 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002042 /* Remember current print column before continuing. */
2043 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002044 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002045 cleanup();
2046 return -1;
2047 }
2048 }
2049 return 0;
2050}
2051
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002052void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053tprintf(const char *fmt, ...)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054{
2055 va_list args;
2056
Andreas Schwabe5355de2009-10-27 16:56:43 +01002057 va_start(args, fmt);
Roland McGrathb310a0c2003-11-06 23:41:22 +00002058 if (outf) {
2059 int n = vfprintf(outf, fmt, args);
Andreas Schwabccdff482009-10-27 16:27:13 +01002060 if (n < 0) {
2061 if (outf != stderr)
2062 perror(outfname == NULL
2063 ? "<writing to pipe>" : outfname);
2064 } else
Roland McGrathb310a0c2003-11-06 23:41:22 +00002065 curcol += n;
2066 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 va_end(args);
Denys Vlasenko5940e652011-09-01 09:55:05 +02002068}
2069
2070void
2071tprints(const char *str)
2072{
2073 if (outf) {
2074 int n = fputs(str, outf);
2075 if (n >= 0) {
2076 curcol += strlen(str);
2077 return;
2078 }
2079 if (outf != stderr)
2080 perror(outfname == NULL
2081 ? "<writing to pipe>" : outfname);
2082 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083}
2084
2085void
Denys Vlasenko12014262011-05-30 14:00:14 +02002086printleader(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002087{
Denys Vlasenko000b6012012-01-28 01:25:03 +01002088 if (printing_tcp) {
2089 if (printing_tcp->ptrace_errno) {
2090 if (printing_tcp->flags & TCB_INSYSCALL) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002091 tprints(" <unavailable>) ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002092 tabto();
Denys Vlasenko7e0615f2009-01-28 19:00:54 +00002093 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002094 tprints("= ? <unavailable>\n");
Denys Vlasenko000b6012012-01-28 01:25:03 +01002095 printing_tcp->ptrace_errno = 0;
2096 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2097 printing_tcp->flags |= TCB_REPRINT;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002098 tprints(" <unfinished ...>\n");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002099 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002100 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002101
2102 printing_tcp = tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103 curcol = 0;
Denys Vlasenkofd883382012-03-09 13:03:41 +01002104
2105 if (print_pid_pfx)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106 tprintf("%-5d ", tcp->pid);
2107 else if (nprocs > 1 && !outfname)
2108 tprintf("[pid %5u] ", tcp->pid);
Denys Vlasenkofd883382012-03-09 13:03:41 +01002109
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 if (tflag) {
2111 char str[sizeof("HH:MM:SS")];
2112 struct timeval tv, dtv;
2113 static struct timeval otv;
2114
2115 gettimeofday(&tv, NULL);
2116 if (rflag) {
2117 if (otv.tv_sec == 0)
2118 otv = tv;
2119 tv_sub(&dtv, &tv, &otv);
2120 tprintf("%6ld.%06ld ",
2121 (long) dtv.tv_sec, (long) dtv.tv_usec);
2122 otv = tv;
2123 }
2124 else if (tflag > 2) {
2125 tprintf("%ld.%06ld ",
2126 (long) tv.tv_sec, (long) tv.tv_usec);
2127 }
2128 else {
2129 time_t local = tv.tv_sec;
2130 strftime(str, sizeof(str), "%T", localtime(&local));
2131 if (tflag > 1)
2132 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
2133 else
2134 tprintf("%s ", str);
2135 }
2136 }
2137 if (iflag)
2138 printcall(tcp);
2139}
2140
2141void
Denys Vlasenko102ec492011-08-25 01:27:59 +02002142tabto(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002143{
Denys Vlasenko102ec492011-08-25 01:27:59 +02002144 if (curcol < acolumn)
Denys Vlasenko5940e652011-09-01 09:55:05 +02002145 tprints(acolumn_spaces + curcol);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146}