blob: 6196e67e02949830728f25072d9b8764d0883aac [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
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100340void
341tprintf(const char *fmt, ...)
342{
343 va_list args;
344
345 va_start(args, fmt);
346 if (outf) {
347 int n = vfprintf(outf, fmt, args);
348 if (n < 0) {
349 if (outf != stderr)
350 perror(outfname == NULL
351 ? "<writing to pipe>" : outfname);
352 } else
353 curcol += n;
354 }
355 va_end(args);
356}
357
358void
359tprints(const char *str)
360{
361 if (outf) {
362 int n = fputs(str, outf);
363 if (n >= 0) {
364 curcol += strlen(str);
365 return;
366 }
367 if (outf != stderr)
368 perror(outfname == NULL
369 ? "<writing to pipe>" : outfname);
370 }
371}
372
373void
374printleader(struct tcb *tcp)
375{
376 if (printing_tcp) {
377 if (printing_tcp->ptrace_errno) {
378 if (printing_tcp->flags & TCB_INSYSCALL) {
379 tprints(" <unavailable>) ");
380 tabto();
381 }
382 tprints("= ? <unavailable>\n");
383 printing_tcp->ptrace_errno = 0;
384 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
385 printing_tcp->flags |= TCB_REPRINT;
386 tprints(" <unfinished ...>\n");
387 }
388 }
389
390 printing_tcp = tcp;
391 curcol = 0;
392
393 if (print_pid_pfx)
394 tprintf("%-5d ", tcp->pid);
395 else if (nprocs > 1 && !outfname)
396 tprintf("[pid %5u] ", tcp->pid);
397
398 if (tflag) {
399 char str[sizeof("HH:MM:SS")];
400 struct timeval tv, dtv;
401 static struct timeval otv;
402
403 gettimeofday(&tv, NULL);
404 if (rflag) {
405 if (otv.tv_sec == 0)
406 otv = tv;
407 tv_sub(&dtv, &tv, &otv);
408 tprintf("%6ld.%06ld ",
409 (long) dtv.tv_sec, (long) dtv.tv_usec);
410 otv = tv;
411 }
412 else if (tflag > 2) {
413 tprintf("%ld.%06ld ",
414 (long) tv.tv_sec, (long) tv.tv_usec);
415 }
416 else {
417 time_t local = tv.tv_sec;
418 strftime(str, sizeof(str), "%T", localtime(&local));
419 if (tflag > 1)
420 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
421 else
422 tprintf("%s ", str);
423 }
424 }
425 if (iflag)
426 printcall(tcp);
427}
428
429void
430tabto(void)
431{
432 if (curcol < acolumn)
433 tprints(acolumn_spaces + curcol);
434}
435
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000436/*
437 * When strace is setuid executable, we have to swap uids
438 * before and after filesystem and process management operations.
439 */
440static void
441swap_uid(void)
442{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000443 int euid = geteuid(), uid = getuid();
444
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200445 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200446 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000447 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000448}
449
Roland McGrath4bfa6262007-07-05 20:03:16 +0000450#if _LFS64_LARGEFILE
451# define fopen_for_output fopen64
452#else
453# define fopen_for_output fopen
454#endif
455
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000456static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200457strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000458{
459 FILE *fp;
460
461 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200462 fp = fopen_for_output(path, "w");
463 if (!fp)
464 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000465 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200466 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000467 return fp;
468}
469
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200470static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000471
472#ifndef _PATH_BSHELL
473# define _PATH_BSHELL "/bin/sh"
474#endif
475
476/*
477 * We cannot use standard popen(3) here because we have to distinguish
478 * popen child process from other processes we trace, and standard popen(3)
479 * does not export its child's pid.
480 */
481static FILE *
482strace_popen(const char *command)
483{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200484 FILE *fp;
485 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000486
487 swap_uid();
488 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200489 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000490
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200491 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000492
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200493 popen_pid = vfork();
494 if (popen_pid == -1)
495 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000496
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200497 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000498 /* child */
499 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200500 if (fds[0] != 0) {
501 if (dup2(fds[0], 0))
502 perror_msg_and_die("dup2");
503 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000504 }
505 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200506 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000507 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200508
509 /* parent */
510 close(fds[0]);
511 swap_uid();
512 fp = fdopen(fds[1], "w");
513 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200514 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200515 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000516}
517
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200518static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000519newoutf(struct tcb *tcp)
520{
521 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000522 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000523 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200524 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000525 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000526}
527
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100528static void process_opt_p_list(char *opt)
529{
530 while (*opt) {
531 /*
532 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
533 * pidof uses space as delim, pgrep uses newline. :(
534 */
535 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100536 char *delim = opt + strcspn(opt, ", \n\t");
537 char c = *delim;
538
539 *delim = '\0';
540 pid = atoi(opt); /* TODO: stricter parsing of the number? */
541 if (pid <= 0) {
542 error_msg("Invalid process id: '%s'", opt);
543 *delim = c;
544 return;
545 }
546 if (pid == strace_tracer_pid) {
547 error_msg("I'm sorry, I can't let you do that, Dave.");
548 *delim = c;
549 return;
550 }
551 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100552 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100553 if (c == '\0')
554 break;
555 opt = delim + 1;
556 }
557}
558
Roland McGrath02203312007-06-11 22:06:31 +0000559static void
560startup_attach(void)
561{
562 int tcbi;
563 struct tcb *tcp;
564
565 /*
566 * Block user interruptions as we would leave the traced
567 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200568 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200569 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000570 */
571 if (interactive)
572 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
573
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000574 if (daemonized_tracer) {
575 pid_t pid = fork();
576 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200577 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 }
579 if (pid) { /* parent */
580 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200581 * Wait for grandchild to attach to straced process
582 * (grandparent). Grandchild SIGKILLs us after it attached.
583 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000584 * it proceeds to exec the straced program.
585 */
586 pause();
587 _exit(0); /* paranoia */
588 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200589 /* grandchild */
590 /* We will be the tracer process. Remember our new pid: */
591 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000592 }
593
Roland McGrath02203312007-06-11 22:06:31 +0000594 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
595 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200596
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100597 if (!(tcp->flags & TCB_INUSE))
598 continue;
599
Denys Vlasenkod116a732011-09-05 14:01:33 +0200600 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100601 if (tcp->flags & TCB_ATTACHED)
602 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200603
604 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000605 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200606 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000607
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000608 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000609 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000610 DIR *dir;
611
612 sprintf(procdir, "/proc/%d/task", tcp->pid);
613 dir = opendir(procdir);
614 if (dir != NULL) {
615 unsigned int ntid = 0, nerr = 0;
616 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200617
Roland McGrath02203312007-06-11 22:06:31 +0000618 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200619 struct tcb *cur_tcp;
620 int tid;
621
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000622 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000623 continue;
624 tid = atoi(de->d_name);
625 if (tid <= 0)
626 continue;
627 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100628 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000629 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200630 if (debug)
631 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200632 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200633 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200634 if (debug)
635 fprintf(stderr, "attach to pid %d succeeded\n", tid);
636 cur_tcp = tcp;
637 if (tid != tcp->pid)
638 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100639 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000640 }
641 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200642 if (interactive) {
643 sigprocmask(SIG_SETMASK, &empty_set, NULL);
644 if (interrupted)
645 goto ret;
646 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
647 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000648 ntid -= nerr;
649 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000650 perror("attach: ptrace(PTRACE_ATTACH, ...)");
651 droptcb(tcp);
652 continue;
653 }
654 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000655 fprintf(stderr, ntid > 1
656? "Process %u attached with %u threads - interrupt to quit\n"
657: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200658 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000659 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100660 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200661 /* -p PID, we failed to attach to PID itself
662 * but did attach to some of its sibling threads.
663 * Drop PID's tcp.
664 */
665 droptcb(tcp);
666 }
Roland McGrath02203312007-06-11 22:06:31 +0000667 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000668 } /* if (opendir worked) */
669 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100670 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000671 perror("attach: ptrace(PTRACE_ATTACH, ...)");
672 droptcb(tcp);
673 continue;
674 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100675 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200676 if (debug)
677 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678
679 if (daemonized_tracer) {
680 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000681 * Make parent go away.
682 * Also makes grandparent's wait() unblock.
683 */
684 kill(getppid(), SIGKILL);
685 }
686
Roland McGrath02203312007-06-11 22:06:31 +0000687 if (!qflag)
688 fprintf(stderr,
689 "Process %u attached - interrupt to quit\n",
690 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200691 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000692
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200693 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000694 if (interactive)
695 sigprocmask(SIG_SETMASK, &empty_set, NULL);
696}
697
698static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200699startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000700{
701 struct stat statbuf;
702 const char *filename;
703 char pathname[MAXPATHLEN];
704 int pid = 0;
705 struct tcb *tcp;
706
707 filename = argv[0];
708 if (strchr(filename, '/')) {
709 if (strlen(filename) > sizeof pathname - 1) {
710 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200711 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000712 }
713 strcpy(pathname, filename);
714 }
715#ifdef USE_DEBUGGING_EXEC
716 /*
717 * Debuggers customarily check the current directory
718 * first regardless of the path but doing that gives
719 * security geeks a panic attack.
720 */
721 else if (stat(filename, &statbuf) == 0)
722 strcpy(pathname, filename);
723#endif /* USE_DEBUGGING_EXEC */
724 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000725 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000726 int m, n, len;
727
728 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100729 const char *colon = strchr(path, ':');
730 if (colon) {
731 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000732 m = n + 1;
733 }
734 else
735 m = n = strlen(path);
736 if (n == 0) {
737 if (!getcwd(pathname, MAXPATHLEN))
738 continue;
739 len = strlen(pathname);
740 }
741 else if (n > sizeof pathname - 1)
742 continue;
743 else {
744 strncpy(pathname, path, n);
745 len = n;
746 }
747 if (len && pathname[len - 1] != '/')
748 pathname[len++] = '/';
749 strcpy(pathname + len, filename);
750 if (stat(pathname, &statbuf) == 0 &&
751 /* Accept only regular files
752 with some execute bits set.
753 XXX not perfect, might still fail */
754 S_ISREG(statbuf.st_mode) &&
755 (statbuf.st_mode & 0111))
756 break;
757 }
758 }
759 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200760 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000761 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000762 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000763 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200764 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000765 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200766 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
767 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000768 ) {
769 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200770 if (outf != stderr)
771 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100772 if (!daemonized_tracer && !use_seize) {
773 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200774 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000775 }
Roland McGrath02203312007-06-11 22:06:31 +0000776 }
Roland McGrath02203312007-06-11 22:06:31 +0000777
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200778 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000779 uid_t run_euid = run_uid;
780 gid_t run_egid = run_gid;
781
782 if (statbuf.st_mode & S_ISUID)
783 run_euid = statbuf.st_uid;
784 if (statbuf.st_mode & S_ISGID)
785 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000786 /*
787 * It is important to set groups before we
788 * lose privileges on setuid.
789 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200790 if (initgroups(username, run_gid) < 0) {
791 perror_msg_and_die("initgroups");
792 }
793 if (setregid(run_gid, run_egid) < 0) {
794 perror_msg_and_die("setregid");
795 }
796 if (setreuid(run_uid, run_euid) < 0) {
797 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000798 }
799 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200800 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000801 setreuid(run_uid, run_uid);
802
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000803 if (!daemonized_tracer) {
804 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200805 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000806 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200807 * the immediately following execve syscall.
808 * Can't do this on NOMMU systems, we are after
809 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000810 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400811 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200812 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000813 } else {
814 struct sigaction sv_sigchld;
815 sigaction(SIGCHLD, NULL, &sv_sigchld);
816 /*
817 * Make sure it is not SIG_IGN, otherwise wait
818 * will not block.
819 */
820 signal(SIGCHLD, SIG_DFL);
821 /*
822 * Wait for grandchild to attach to us.
823 * It kills child after that, and wait() unblocks.
824 */
825 alarm(3);
826 wait(NULL);
827 alarm(0);
828 sigaction(SIGCHLD, &sv_sigchld, NULL);
829 }
Roland McGrath02203312007-06-11 22:06:31 +0000830
831 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200832 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000833 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000834
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200835 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200836
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200837 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100838 if (!use_seize) {
839 /* child did PTRACE_TRACEME, nothing to do in parent */
840 } else {
841 if (!strace_vforked) {
842 /* Wait until child stopped itself */
843 int status;
844 while (waitpid(pid, &status, WSTOPPED) < 0) {
845 if (errno == EINTR)
846 continue;
847 perror_msg_and_die("waitpid");
848 }
849 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100850 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100851 perror_msg_and_die("Unexpected wait status %x", status);
852 }
853 }
854 /* Else: vforked case, we have no way to sync.
855 * Just attach to it as soon as possible.
856 * This means that we may miss a few first syscalls...
857 */
858
859 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100860 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100861 perror_msg_and_die("Can't attach to %d", pid);
862 }
863 if (!strace_vforked)
864 kill(pid, SIGCONT);
865 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200866 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200867 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100868 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200869 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100870 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200871 }
872 else {
873 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
874 strace_tracer_pid = getpid();
875 /* The tracee is our parent: */
876 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100877 alloctcb(pid);
878 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000879 }
Roland McGrath02203312007-06-11 22:06:31 +0000880}
881
Wang Chaob13c0de2010-11-12 17:25:19 +0800882/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000883 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800884 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000885 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800886 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000887static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200888test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800889{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000890 int pid, expected_grandchild = 0, found_grandchild = 0;
891 const unsigned int test_options = PTRACE_O_TRACECLONE |
892 PTRACE_O_TRACEFORK |
893 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800894
Denys Vlasenko5d645812011-08-20 12:48:18 +0200895 pid = fork();
896 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000897 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200898 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000899 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100900 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000901 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
902 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100903 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000904 if (fork() < 0)
905 perror_msg_and_die("fork");
906 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800907 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000908
909 while (1) {
910 int status, tracee_pid;
911
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000912 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000913 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000914 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000915 if (errno == EINTR)
916 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100917 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000918 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000919 kill_save_errno(pid, SIGKILL);
920 perror_msg_and_die("%s: unexpected wait result %d",
921 __func__, tracee_pid);
922 }
923 if (WIFEXITED(status)) {
924 if (WEXITSTATUS(status)) {
925 if (tracee_pid != pid)
926 kill_save_errno(pid, SIGKILL);
927 error_msg_and_die("%s: unexpected exit status %u",
928 __func__, WEXITSTATUS(status));
929 }
930 continue;
931 }
932 if (WIFSIGNALED(status)) {
933 if (tracee_pid != pid)
934 kill_save_errno(pid, SIGKILL);
935 error_msg_and_die("%s: unexpected signal %u",
936 __func__, WTERMSIG(status));
937 }
938 if (!WIFSTOPPED(status)) {
939 if (tracee_pid != pid)
940 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100941 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000942 error_msg_and_die("%s: unexpected wait status %x",
943 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000944 }
945 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000946 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000947 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
948 kill_save_errno(tracee_pid, SIGKILL);
949 kill_save_errno(pid, SIGKILL);
950 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800951 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000952 continue;
953 }
954 switch (WSTOPSIG(status)) {
955 case SIGSTOP:
956 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
957 && errno != EINVAL && errno != EIO)
958 perror_msg("PTRACE_SETOPTIONS");
959 break;
960 case SIGTRAP:
961 if (status >> 16 == PTRACE_EVENT_FORK) {
962 long msg = 0;
963
964 if (ptrace(PTRACE_GETEVENTMSG, pid,
965 NULL, (long) &msg) == 0)
966 expected_grandchild = msg;
967 }
968 break;
969 }
970 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
971 kill_save_errno(pid, SIGKILL);
972 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800973 }
974 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000975 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200976 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000977 if (debug)
978 fprintf(stderr, "ptrace_setoptions = %#x\n",
979 ptrace_setoptions);
980 return;
981 }
982 error_msg("Test for PTRACE_O_TRACECLONE failed, "
983 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800984}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200985
986/*
987 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
988 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
989 * and then see whether it will stop with (SIGTRAP | 0x80).
990 *
991 * Use of this option enables correct handling of user-generated SIGTRAPs,
992 * and SIGTRAPs generated by special instructions such as int3 on x86:
993 * _start: .globl _start
994 * int3
995 * movl $42, %ebx
996 * movl $1, %eax
997 * int $0x80
998 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
999 */
1000static void
1001test_ptrace_setoptions_for_all(void)
1002{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001003 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1004 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001005 int pid;
1006 int it_worked = 0;
1007
1008 pid = fork();
1009 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001010 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001011
1012 if (pid == 0) {
1013 pid = getpid();
1014 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001015 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001016 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1017 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001018 kill(pid, SIGSTOP);
1019 _exit(0); /* parent should see entry into this syscall */
1020 }
1021
1022 while (1) {
1023 int status, tracee_pid;
1024
1025 errno = 0;
1026 tracee_pid = wait(&status);
1027 if (tracee_pid <= 0) {
1028 if (errno == EINTR)
1029 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001030 kill_save_errno(pid, SIGKILL);
1031 perror_msg_and_die("%s: unexpected wait result %d",
1032 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001033 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001034 if (WIFEXITED(status)) {
1035 if (WEXITSTATUS(status) == 0)
1036 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001037 error_msg_and_die("%s: unexpected exit status %u",
1038 __func__, WEXITSTATUS(status));
1039 }
1040 if (WIFSIGNALED(status)) {
1041 error_msg_and_die("%s: unexpected signal %u",
1042 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001043 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001044 if (!WIFSTOPPED(status)) {
1045 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001046 error_msg_and_die("%s: unexpected wait status %x",
1047 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001048 }
1049 if (WSTOPSIG(status) == SIGSTOP) {
1050 /*
1051 * We don't check "options aren't accepted" error.
1052 * If it happens, we'll never get (SIGTRAP | 0x80),
1053 * and thus will decide to not use the option.
1054 * IOW: the outcome of the test will be correct.
1055 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001056 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1057 && errno != EINVAL && errno != EIO)
1058 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001059 }
1060 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1061 it_worked = 1;
1062 }
1063 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001064 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001065 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001066 }
1067 }
1068
1069 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001070 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001071 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001072 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001073 fprintf(stderr, "ptrace_setoptions = %#x\n",
1074 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001075 return;
1076 }
1077
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001078 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1079 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001080}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001081
1082# ifdef USE_SEIZE
1083static void
1084test_ptrace_seize(void)
1085{
1086 int pid;
1087
1088 pid = fork();
1089 if (pid < 0)
1090 perror_msg_and_die("fork");
1091
1092 if (pid == 0) {
1093 pause();
1094 _exit(0);
1095 }
1096
1097 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1098 * attaching tracee continues to run unless a trap condition occurs.
1099 * PTRACE_SEIZE doesn't affect signal or group stop state.
1100 */
1101 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1102 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1103 } else if (debug) {
1104 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1105 }
1106
1107 kill(pid, SIGKILL);
1108
1109 while (1) {
1110 int status, tracee_pid;
1111
1112 errno = 0;
1113 tracee_pid = waitpid(pid, &status, 0);
1114 if (tracee_pid <= 0) {
1115 if (errno == EINTR)
1116 continue;
1117 perror_msg_and_die("%s: unexpected wait result %d",
1118 __func__, tracee_pid);
1119 }
1120 if (WIFSIGNALED(status)) {
1121 return;
1122 }
1123 error_msg_and_die("%s: unexpected wait status %x",
1124 __func__, status);
1125 }
1126}
1127# else /* !USE_SEIZE */
1128# define test_ptrace_seize() ((void)0)
1129# endif
1130
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001131/* Noinline: don't want main to have struct utsname permanently on stack */
1132static void __attribute__ ((noinline))
1133get_os_release(void)
1134{
1135 struct utsname u;
1136 if (uname(&u) < 0)
1137 perror_msg_and_die("uname");
1138 os_release = strdup(u.release);
1139 if (!os_release)
1140 die_out_of_memory();
1141}
1142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143int
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001144main(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001147 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001148 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 struct sigaction sa;
1150
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001151 progname = argv[0] ? argv[0] : "strace";
1152
Denys Vlasenko75422762011-05-27 14:36:01 +02001153 strace_tracer_pid = getpid();
1154
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001155 get_os_release();
1156
Roland McGrathee9d4352002-12-18 04:16:10 +00001157 /* Allocate the initial tcbtab. */
1158 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001159 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001160 if (!tcbtab)
1161 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001162 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001163 if (!tcp)
1164 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001165 for (c = 0; c < tcbtabsize; c++)
1166 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001167
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001169 set_sortby(DEFAULT_SORTBY);
1170 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 qualify("trace=all");
1172 qualify("abbrev=all");
1173 qualify("verbose=all");
1174 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001176 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001177 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001178 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179 switch (c) {
1180 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001181 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001182 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001183 }
1184 cflag = CFLAG_ONLY_STATS;
1185 break;
1186 case 'C':
1187 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001188 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001189 }
1190 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 break;
1192 case 'd':
1193 debug++;
1194 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001195 case 'D':
1196 daemonized_tracer = 1;
1197 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001198 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001199 optF = 1;
1200 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 case 'f':
1202 followfork++;
1203 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 case 'h':
1205 usage(stdout, 0);
1206 break;
1207 case 'i':
1208 iflag++;
1209 break;
1210 case 'q':
1211 qflag++;
1212 break;
1213 case 'r':
1214 rflag++;
1215 tflag++;
1216 break;
1217 case 't':
1218 tflag++;
1219 break;
1220 case 'T':
1221 dtime++;
1222 break;
1223 case 'x':
1224 xflag++;
1225 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001226 case 'y':
1227 show_fd_path = 1;
1228 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 case 'v':
1230 qualify("abbrev=none");
1231 break;
1232 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001233 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 exit(0);
1235 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001236 case 'z':
1237 not_failing_only = 1;
1238 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 case 'a':
1240 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001241 if (acolumn < 0)
1242 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001243 break;
1244 case 'e':
1245 qualify(optarg);
1246 break;
1247 case 'o':
1248 outfname = strdup(optarg);
1249 break;
1250 case 'O':
1251 set_overhead(atoi(optarg));
1252 break;
1253 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001254 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001255 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001256 case 'P':
1257 tracing_paths = 1;
1258 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001259 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001260 }
1261 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 case 's':
1263 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001264 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001265 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001266 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001267 break;
1268 case 'S':
1269 set_sortby(optarg);
1270 break;
1271 case 'u':
1272 username = strdup(optarg);
1273 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001274 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001275 if (putenv(optarg) < 0)
1276 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001277 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001278 case 'I':
1279 opt_intr = atoi(optarg);
1280 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1281 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1282 }
1283 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 default:
1285 usage(stderr, 1);
1286 break;
1287 }
1288 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001289 argv += optind;
1290 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291
Denys Vlasenko102ec492011-08-25 01:27:59 +02001292 acolumn_spaces = malloc(acolumn + 1);
1293 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001294 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001295 memset(acolumn_spaces, ' ', acolumn);
1296 acolumn_spaces[acolumn] = '\0';
1297
Denys Vlasenko837399a2012-01-24 11:37:03 +01001298 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001299 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001300 usage(stderr, 1);
1301
Denys Vlasenkofd883382012-03-09 13:03:41 +01001302 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001303 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001304 }
1305
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001306 if (!followfork)
1307 followfork = optF;
1308
Roland McGrathcb9def62006-04-25 07:48:03 +00001309 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001310 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001311 }
1312
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313 /* See if they want to run as another user. */
1314 if (username != NULL) {
1315 struct passwd *pent;
1316
1317 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001318 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001320 pent = getpwnam(username);
1321 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001322 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 }
1324 run_uid = pent->pw_uid;
1325 run_gid = pent->pw_gid;
1326 }
1327 else {
1328 run_uid = getuid();
1329 run_gid = getgid();
1330 }
1331
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001332 if (followfork)
1333 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001334 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001335 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 /* Check if they want to redirect the output. */
1338 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001339 /* See if they want to pipe the output. */
1340 if (outfname[0] == '|' || outfname[0] == '!') {
1341 /*
1342 * We can't do the <outfname>.PID funny business
1343 * when using popen, so prohibit it.
1344 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001345 if (followfork > 1)
1346 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1347 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001348 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001349 else if (followfork <= 1)
1350 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001351 }
1352
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001353 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001354 char *buf = malloc(BUFSIZ);
1355 if (!buf)
1356 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001358 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001359 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001360 if (!opt_intr)
1361 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001363 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001364 if (!opt_intr)
1365 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001366
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001367 /* argv[0] -pPID -oFILE Default interactive setting
1368 * yes 0 0 INTR_WHILE_WAIT
1369 * no 1 0 INTR_WHILE_WAIT
1370 * yes 0 1 INTR_NEVER
1371 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001372 */
1373
1374 /* STARTUP_CHILD must be called before the signal handlers get
1375 installed below as they are inherited into the spawned process.
1376 Also we do not need to be protected by them as during interruption
1377 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001378 if (argv[0])
1379 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001381 sigemptyset(&empty_set);
1382 sigemptyset(&blocked_set);
1383 sa.sa_handler = SIG_IGN;
1384 sigemptyset(&sa.sa_mask);
1385 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001386 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1387 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1388 if (opt_intr != INTR_ANYWHERE) {
1389 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1390 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1391 /*
1392 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1393 * fatal signals are blocked while syscall stop is processed,
1394 * and acted on in between, when waiting for new syscall stops.
1395 * In non-interactive mode, signals are ignored.
1396 */
1397 if (opt_intr == INTR_WHILE_WAIT) {
1398 sigaddset(&blocked_set, SIGHUP);
1399 sigaddset(&blocked_set, SIGINT);
1400 sigaddset(&blocked_set, SIGQUIT);
1401 sigaddset(&blocked_set, SIGPIPE);
1402 sigaddset(&blocked_set, SIGTERM);
1403 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001404 }
1405 /* SIG_IGN, or set handler for these */
1406 sigaction(SIGHUP, &sa, NULL);
1407 sigaction(SIGINT, &sa, NULL);
1408 sigaction(SIGQUIT, &sa, NULL);
1409 sigaction(SIGPIPE, &sa, NULL);
1410 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 }
Roland McGrath553a6092002-12-16 20:40:39 +00001412 /* Make sure SIGCHLD has the default action so that waitpid
1413 definitely works without losing track of children. The user
1414 should not have given us a bogus state to inherit, but he might
1415 have. Arguably we should detect SIG_IGN here and pass it on
1416 to children, but probably noone really needs that. */
1417 sa.sa_handler = SIG_DFL;
1418 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001419
Denys Vlasenkofd883382012-03-09 13:03:41 +01001420 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001421 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001422
Denys Vlasenkofd883382012-03-09 13:03:41 +01001423 /* Do we want pids printed in our -o OUTFILE?
1424 * -ff: no (every pid has its own file); or
1425 * -f: yes (there can be more pids in the future); or
1426 * -p PID1,PID2: yes (there are already more than one pid)
1427 */
1428 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
1429
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430 if (trace() < 0)
1431 exit(1);
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001432
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 cleanup();
Dmitry V. Levina6809652008-11-10 17:14:58 +00001434 fflush(NULL);
1435 if (exit_code > 0xff) {
Dmitry V. Levin6c381562012-02-22 00:15:27 +00001436 /* Avoid potential core file clobbering. */
1437 struct rlimit rlim = {0, 0};
1438 setrlimit(RLIMIT_CORE, &rlim);
1439
Dmitry V. Levina6809652008-11-10 17:14:58 +00001440 /* Child was killed by a signal, mimic that. */
1441 exit_code &= 0xff;
1442 signal(exit_code, SIG_DFL);
1443 raise(exit_code);
1444 /* Paranoia - what if this signal is not fatal?
1445 Exit with 128 + signo then. */
1446 exit_code += 128;
1447 }
1448 exit(exit_code);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449}
1450
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001451static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001452expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001453{
1454 /* Allocate some more TCBs and expand the table.
1455 We don't want to relocate the TCBs because our
1456 callers have pointers and it would be a pain.
1457 So tcbtab is a table of pointers. Since we never
1458 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001459 int i = tcbtabsize;
1460 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1461 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001462 if (!newtab || !newtcbs)
1463 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001464 tcbtabsize *= 2;
1465 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001466 while (i < tcbtabsize)
1467 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001468}
1469
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001471alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472{
1473 int i;
1474 struct tcb *tcp;
1475
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001476 if (nprocs == tcbtabsize)
1477 expand_tcbtab();
1478
Roland McGrathee9d4352002-12-18 04:16:10 +00001479 for (i = 0; i < tcbtabsize; i++) {
1480 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001482 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001484 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001486#if SUPPORTED_PERSONALITIES > 1
1487 tcp->currpers = current_personality;
1488#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001490 if (debug)
1491 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001492 if (command_options_parsed)
1493 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 return tcp;
1495 }
1496 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001497 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498}
1499
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001500static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001501pid2tcb(int pid)
1502{
1503 int i;
1504
1505 if (pid <= 0)
1506 return NULL;
1507
1508 for (i = 0; i < tcbtabsize; i++) {
1509 struct tcb *tcp = tcbtab[i];
1510 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1511 return tcp;
1512 }
1513
1514 return NULL;
1515}
1516
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517void
Denys Vlasenko12014262011-05-30 14:00:14 +02001518droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519{
1520 if (tcp->pid == 0)
1521 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001522
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001524 if (debug)
1525 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001526
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001527 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001529
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001530 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531}
1532
Roland McGrath0a463882007-07-05 18:43:16 +00001533/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001534 * Never call DETACH twice on the same process as both unattached and
1535 * attached-unstopped processes give the same ESRCH. For unattached process we
1536 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1537 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001539detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001541 int error;
1542 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543
1544 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001545 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547 /*
1548 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001549 * before detaching. Arghh. We go through hoops
1550 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001551 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001552#if defined(SPARC)
1553#undef PTRACE_DETACH
1554#define PTRACE_DETACH PTRACE_SUNDETACH
1555#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001556
1557 sigstop_expected = 0;
1558 if (tcp->flags & TCB_ATTACHED) {
1559 /*
1560 * We attached but possibly didn't see the expected SIGSTOP.
1561 * We must catch exactly one as otherwise the detached process
1562 * would be left stopped (process state T).
1563 */
1564 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1565 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1566 if (error == 0) {
1567 /* On a clear day, you can see forever. */
1568 }
1569 else if (errno != ESRCH) {
1570 /* Shouldn't happen. */
1571 perror("detach: ptrace(PTRACE_DETACH, ...)");
1572 }
1573 else if (my_tkill(tcp->pid, 0) < 0) {
1574 if (errno != ESRCH)
1575 perror("detach: checking sanity");
1576 }
1577 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1578 if (errno != ESRCH)
1579 perror("detach: stopping child");
1580 }
1581 else
1582 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001583 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001584
1585 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001587#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001588 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001589 if (errno == ECHILD) /* Already gone. */
1590 break;
1591 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001592 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001593 break;
1594 }
1595#endif /* __WALL */
1596 /* No __WALL here. */
1597 if (waitpid(tcp->pid, &status, 0) < 0) {
1598 if (errno != ECHILD) {
1599 perror("detach: waiting");
1600 break;
1601 }
1602#ifdef __WCLONE
1603 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001604 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001605 if (errno != ECHILD)
1606 perror("detach: waiting");
1607 break;
1608 }
1609#endif /* __WCLONE */
1610 }
1611#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001612 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001613#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 if (!WIFSTOPPED(status)) {
1615 /* Au revoir, mon ami. */
1616 break;
1617 }
1618 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001619 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 break;
1621 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001622 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001623 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001624 : WSTOPSIG(status));
1625 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001628 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001630 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 fprintf(stderr, "Process %u detached\n", tcp->pid);
1632
1633 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001634
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 return error;
1636}
1637
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001639cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640{
1641 int i;
1642 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001643 int fatal_sig;
1644
1645 /* 'interrupted' is a volatile object, fetch it only once */
1646 fatal_sig = interrupted;
1647 if (!fatal_sig)
1648 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649
Roland McGrathee9d4352002-12-18 04:16:10 +00001650 for (i = 0; i < tcbtabsize; i++) {
1651 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652 if (!(tcp->flags & TCB_INUSE))
1653 continue;
1654 if (debug)
1655 fprintf(stderr,
1656 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001657 if (printing_tcp &&
1658 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1659 tprints(" <unfinished ...>\n");
1660 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001662 if (!(tcp->flags & TCB_STRACE_CHILD))
Denys Vlasenko4c196382012-01-04 15:11:09 +01001663 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664 else {
1665 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001666 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667 }
1668 }
1669 if (cflag)
1670 call_summary(outf);
1671}
1672
1673static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001674interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001676 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677}
1678
1679#ifndef HAVE_STRERROR
1680
Roland McGrath6d2b3492002-12-30 00:51:30 +00001681#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682extern int sys_nerr;
1683extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001684#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685
1686const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001687strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001689 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001691 if (err_no < 1 || err_no >= sys_nerr) {
1692 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693 return buf;
1694 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001695 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696}
1697
1698#endif /* HAVE_STERRROR */
1699
1700#ifndef HAVE_STRSIGNAL
1701
Roland McGrath8f474e02003-01-14 07:53:33 +00001702#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001703extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001705#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1706extern char *_sys_siglist[];
1707#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708
1709const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001710strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001712 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713
1714 if (sig < 1 || sig >= NSIG) {
1715 sprintf(buf, "Unknown signal %d", sig);
1716 return buf;
1717 }
1718#ifdef HAVE__SYS_SIGLIST
1719 return _sys_siglist[sig];
1720#else
1721 return sys_siglist[sig];
1722#endif
1723}
1724
1725#endif /* HAVE_STRSIGNAL */
1726
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001728trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001731 struct rusage *rup = cflag ? &ru : NULL;
1732# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001733 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001734# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735
Roland McGratheb9e2e82009-06-02 16:49:22 -07001736 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001737 int pid;
1738 int wait_errno;
1739 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001740 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001741 struct tcb *tcp;
1742 unsigned event;
1743
Denys Vlasenko222713a2009-03-17 14:29:59 +00001744 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001745 return 0;
1746 if (interactive)
1747 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001748# ifdef __WALL
1749 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001750 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001751 /* this kernel does not support __WALL */
1752 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001753 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001754 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001755 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001756 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001757 pid = wait4(-1, &status, __WCLONE, rup);
1758 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001759 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001760 }
1761 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001762# else
1763 pid = wait4(-1, &status, 0, rup);
1764# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001766 if (interactive)
1767 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001769 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001770 switch (wait_errno) {
1771 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001773 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 /*
1775 * We would like to verify this case
1776 * but sometimes a race in Solbourne's
1777 * version of SunOS sometimes reports
1778 * ECHILD before sending us SIGCHILD.
1779 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001780 return 0;
1781 default:
1782 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001783 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001784 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 }
1786 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001787 if (pid == popen_pid) {
1788 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001789 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001790 continue;
1791 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001792
1793 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001794 if (debug) {
1795 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001796 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001797 static const char *const event_names[] = {
1798 [PTRACE_EVENT_CLONE] = "CLONE",
1799 [PTRACE_EVENT_FORK] = "FORK",
1800 [PTRACE_EVENT_VFORK] = "VFORK",
1801 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1802 [PTRACE_EVENT_EXEC] = "EXEC",
1803 [PTRACE_EVENT_EXIT] = "EXIT",
1804 };
1805 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001806 if (event < ARRAY_SIZE(event_names))
1807 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001808 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001809 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001810 e = buf;
1811 }
1812 fprintf(stderr, " PTRACE_EVENT_%s", e);
1813 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001814 strcpy(buf, "???");
1815 if (WIFSIGNALED(status))
1816#ifdef WCOREDUMP
1817 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1818 WCOREDUMP(status) ? "core," : "",
1819 signame(WTERMSIG(status)));
1820#else
1821 sprintf(buf, "WIFSIGNALED,sig=%s",
1822 signame(WTERMSIG(status)));
1823#endif
1824 if (WIFEXITED(status))
1825 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1826 if (WIFSTOPPED(status))
1827 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001828#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001829 if (WIFCONTINUED(status))
1830 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001831#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001832 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1833 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001834
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001835 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001836 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001837
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001838 /* Under Linux, execve changes pid to thread leader's pid,
1839 * and we see this changed pid on EVENT_EXEC and later,
1840 * execve sysexit. Leader "disappears" without exit
1841 * notification. Let user know that, drop leader's tcb,
1842 * and fix up pid in execve thread's tcb.
1843 * Effectively, execve thread's tcb replaces leader's tcb.
1844 *
1845 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1846 * on exit syscall) in multithreaded programs exactly
1847 * in order to handle this case.
1848 *
1849 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1850 * On 2.6 and earlier, it can return garbage.
1851 */
1852 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1853 long old_pid = 0;
1854 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1855 && old_pid > 0
1856 && old_pid != pid
1857 ) {
1858 struct tcb *execve_thread = pid2tcb(old_pid);
1859 if (tcp) {
1860 outf = tcp->outf;
1861 curcol = tcp->curcol;
1862 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001863 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001864 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001865 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001866 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1867 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001868 fflush(outf);
1869 }
1870 if (execve_thread) {
1871 /* swap output FILEs (needed for -ff) */
1872 tcp->outf = execve_thread->outf;
1873 execve_thread->outf = outf;
1874 }
1875 droptcb(tcp);
1876 }
1877 tcp = execve_thread;
1878 if (tcp) {
1879 tcp->pid = pid;
1880 tcp->flags |= TCB_REPRINT;
1881 }
1882 }
1883 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001884
Denys Vlasenko5d645812011-08-20 12:48:18 +02001885 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001886 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001887 /* This is needed to go with the CLONE_PTRACE
1888 changes in process.c/util.c: we might see
1889 the child's initial trap before we see the
1890 parent return from the clone syscall.
1891 Leave the child suspended until the parent
1892 returns from its system call. Only then
1893 will we have the association of parent and
1894 child so that we know how to do clearbpt
1895 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001896 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001897 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001898 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001899 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001900 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001901 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001902 else
1903 /* This can happen if a clone call used
1904 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001905 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001906 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001907 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001908 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001909 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001911 /* set current output file */
1912 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001913 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001914 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1916 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001918
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001920 if (pid == strace_child)
1921 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001922 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1924 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001925#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001926 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001927 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001928 WCOREDUMP(status) ? "(core dumped) " : "");
1929#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001930 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001931 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001932#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001933 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001935 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 droptcb(tcp);
1937 continue;
1938 }
1939 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001940 if (pid == strace_child)
1941 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001942 if (tcp == printing_tcp) {
1943 tprints(" <unfinished ...>\n");
1944 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001945 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001946 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1947 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001948 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1949 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001950 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001951 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 droptcb(tcp);
1953 continue;
1954 }
1955 if (!WIFSTOPPED(status)) {
1956 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1957 droptcb(tcp);
1958 continue;
1959 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001961 /* Is this the very first time we see this tracee stopped? */
1962 if (tcp->flags & TCB_STARTUP) {
1963 if (debug)
1964 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001965 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001966 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001967 /*
1968 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001969 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001970 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001971 if (clearbpt(tcp) < 0) {
1972 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001973 droptcb(tcp);
1974 cleanup();
1975 return -1;
1976 }
1977 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001978 if (ptrace_setoptions) {
1979 if (debug)
1980 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1981 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1982 if (errno != ESRCH) {
1983 /* Should never happen, really */
1984 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001985 }
1986 }
1987 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001988 }
1989
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001990 sig = WSTOPSIG(status);
1991
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001992 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001993 /* Ptrace event */
1994#ifdef USE_SEIZE
1995 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001996 /*
1997 * PTRACE_INTERRUPT-stop or group-stop.
1998 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1999 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002000 if (sig == SIGSTOP
2001 || sig == SIGTSTP
2002 || sig == SIGTTIN
2003 || sig == SIGTTOU
2004 ) {
2005 stopped = 1;
2006 goto show_stopsig;
2007 }
2008 }
2009#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002010 goto restart_tracee_with_sig_0;
2011 }
2012
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002013 /* Is this post-attach SIGSTOP?
2014 * Interestingly, the process may stop
2015 * with STOPSIG equal to some other signal
2016 * than SIGSTOP if we happend to attach
2017 * just before the process takes a signal.
2018 */
2019 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2020 if (debug)
2021 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2022 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002023 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002024 }
2025
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002026 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002027 siginfo_t si;
2028
2029 /* Nonzero (true) if tracee is stopped by signal
2030 * (as opposed to "tracee received signal").
2031 */
2032 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002033#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002034 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002035#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002036 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002037 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002038#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002039 long pc = 0;
2040 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002041
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002042 upeek(tcp, PT_CR_IPSR, &psr);
2043 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002044
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002045# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002046 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002047# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002048# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002049#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002050# define PC_FORMAT_STR ""
2051# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002052#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002053 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002054 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002055 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002056 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002057 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002058 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002059 PC_FORMAT_ARG);
2060 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002061 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002062 strsignal(sig),
2063 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002064 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002065 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002066 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002067 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002068
2069 if (!stopped)
2070 /* It's signal-delivery-stop. Inject the signal */
2071 goto restart_tracee;
2072
2073 /* It's group-stop */
2074#ifdef USE_SEIZE
2075 if (use_seize) {
2076 /*
2077 * This ends ptrace-stop, but does *not* end group-stop.
2078 * This makes stopping signals work properly on straced process
2079 * (that is, process really stops. It used to continue to run).
2080 */
2081 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2082 cleanup();
2083 return -1;
2084 }
2085 continue;
2086 }
2087 /* We don't have PTRACE_LISTEN support... */
2088#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002089 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002090 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002091
2092 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002093 if (interrupted)
2094 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002095
2096 /* This should be syscall entry or exit.
2097 * (Or it still can be that pesky post-execve SIGTRAP!)
2098 * Handle it.
2099 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002100 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2101 /* ptrace() failed in trace_syscall() with ESRCH.
2102 * Likely a result of process disappearing mid-flight.
2103 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002104 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002105 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002106 if (printing_tcp) {
2107 /* Do we have dangling line "syscall(param, param"?
2108 * Finish the line then.
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002109 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002110 printing_tcp->flags |= TCB_REPRINT;
2111 tprints(" <unfinished ...>\n");
2112 printing_tcp = NULL;
2113 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 }
Denys Vlasenkof2025022012-03-09 15:29:45 +01002115 /* We assume that ptrace error was caused by process death.
2116 * We used to detach(tcp) here, but since we no longer
2117 * implement "detach before death" policy/hack,
2118 * we can let this process to report its death to us
2119 * normally, via WIFEXITED or WIFSIGNALED wait status.
2120 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121 continue;
2122 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002123 restart_tracee_with_sig_0:
2124 sig = 0;
2125 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002126 /* Remember current print column before continuing. */
2127 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002128 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 cleanup();
2130 return -1;
2131 }
2132 }
2133 return 0;
2134}