blob: e581882a27096f3278ca3c014af89ab6668561a8 [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 Vlasenko558e5122012-03-12 23:32:16 +0100528static void
529process_opt_p_list(char *opt)
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100530{
531 while (*opt) {
532 /*
533 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
534 * pidof uses space as delim, pgrep uses newline. :(
535 */
536 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100537 char *delim = opt + strcspn(opt, ", \n\t");
538 char c = *delim;
539
540 *delim = '\0';
541 pid = atoi(opt); /* TODO: stricter parsing of the number? */
542 if (pid <= 0) {
543 error_msg("Invalid process id: '%s'", opt);
544 *delim = c;
545 return;
546 }
547 if (pid == strace_tracer_pid) {
548 error_msg("I'm sorry, I can't let you do that, Dave.");
549 *delim = c;
550 return;
551 }
552 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100553 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100554 if (c == '\0')
555 break;
556 opt = delim + 1;
557 }
558}
559
Roland McGrath02203312007-06-11 22:06:31 +0000560static void
561startup_attach(void)
562{
563 int tcbi;
564 struct tcb *tcp;
565
566 /*
567 * Block user interruptions as we would leave the traced
568 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200569 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200570 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000571 */
572 if (interactive)
573 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
574
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000575 if (daemonized_tracer) {
576 pid_t pid = fork();
577 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200578 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000579 }
580 if (pid) { /* parent */
581 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200582 * Wait for grandchild to attach to straced process
583 * (grandparent). Grandchild SIGKILLs us after it attached.
584 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000585 * it proceeds to exec the straced program.
586 */
587 pause();
588 _exit(0); /* paranoia */
589 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200590 /* grandchild */
591 /* We will be the tracer process. Remember our new pid: */
592 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000593 }
594
Roland McGrath02203312007-06-11 22:06:31 +0000595 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
596 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200597
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100598 if (!(tcp->flags & TCB_INUSE))
599 continue;
600
Denys Vlasenkod116a732011-09-05 14:01:33 +0200601 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100602 if (tcp->flags & TCB_ATTACHED)
603 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200604
605 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000606 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200607 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000608
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000609 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000610 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000611 DIR *dir;
612
613 sprintf(procdir, "/proc/%d/task", tcp->pid);
614 dir = opendir(procdir);
615 if (dir != NULL) {
616 unsigned int ntid = 0, nerr = 0;
617 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200618
Roland McGrath02203312007-06-11 22:06:31 +0000619 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200620 struct tcb *cur_tcp;
621 int tid;
622
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000623 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000624 continue;
625 tid = atoi(de->d_name);
626 if (tid <= 0)
627 continue;
628 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100629 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000630 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200631 if (debug)
632 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200633 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200634 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200635 if (debug)
636 fprintf(stderr, "attach to pid %d succeeded\n", tid);
637 cur_tcp = tcp;
638 if (tid != tcp->pid)
639 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100640 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000641 }
642 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200643 if (interactive) {
644 sigprocmask(SIG_SETMASK, &empty_set, NULL);
645 if (interrupted)
646 goto ret;
647 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
648 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000649 ntid -= nerr;
650 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000651 perror("attach: ptrace(PTRACE_ATTACH, ...)");
652 droptcb(tcp);
653 continue;
654 }
655 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000656 fprintf(stderr, ntid > 1
657? "Process %u attached with %u threads - interrupt to quit\n"
658: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200659 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000660 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100661 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200662 /* -p PID, we failed to attach to PID itself
663 * but did attach to some of its sibling threads.
664 * Drop PID's tcp.
665 */
666 droptcb(tcp);
667 }
Roland McGrath02203312007-06-11 22:06:31 +0000668 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000669 } /* if (opendir worked) */
670 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100671 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000672 perror("attach: ptrace(PTRACE_ATTACH, ...)");
673 droptcb(tcp);
674 continue;
675 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100676 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200677 if (debug)
678 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000679
680 if (daemonized_tracer) {
681 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000682 * Make parent go away.
683 * Also makes grandparent's wait() unblock.
684 */
685 kill(getppid(), SIGKILL);
686 }
687
Roland McGrath02203312007-06-11 22:06:31 +0000688 if (!qflag)
689 fprintf(stderr,
690 "Process %u attached - interrupt to quit\n",
691 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200692 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000693
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200694 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000695 if (interactive)
696 sigprocmask(SIG_SETMASK, &empty_set, NULL);
697}
698
699static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200700startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000701{
702 struct stat statbuf;
703 const char *filename;
704 char pathname[MAXPATHLEN];
705 int pid = 0;
706 struct tcb *tcp;
707
708 filename = argv[0];
709 if (strchr(filename, '/')) {
710 if (strlen(filename) > sizeof pathname - 1) {
711 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200712 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000713 }
714 strcpy(pathname, filename);
715 }
716#ifdef USE_DEBUGGING_EXEC
717 /*
718 * Debuggers customarily check the current directory
719 * first regardless of the path but doing that gives
720 * security geeks a panic attack.
721 */
722 else if (stat(filename, &statbuf) == 0)
723 strcpy(pathname, filename);
724#endif /* USE_DEBUGGING_EXEC */
725 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000726 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000727 int m, n, len;
728
729 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100730 const char *colon = strchr(path, ':');
731 if (colon) {
732 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000733 m = n + 1;
734 }
735 else
736 m = n = strlen(path);
737 if (n == 0) {
738 if (!getcwd(pathname, MAXPATHLEN))
739 continue;
740 len = strlen(pathname);
741 }
742 else if (n > sizeof pathname - 1)
743 continue;
744 else {
745 strncpy(pathname, path, n);
746 len = n;
747 }
748 if (len && pathname[len - 1] != '/')
749 pathname[len++] = '/';
750 strcpy(pathname + len, filename);
751 if (stat(pathname, &statbuf) == 0 &&
752 /* Accept only regular files
753 with some execute bits set.
754 XXX not perfect, might still fail */
755 S_ISREG(statbuf.st_mode) &&
756 (statbuf.st_mode & 0111))
757 break;
758 }
759 }
760 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200761 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000762 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000763 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000764 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200765 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000766 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200767 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
768 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000769 ) {
770 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200771 if (outf != stderr)
772 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100773 if (!daemonized_tracer && !use_seize) {
774 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200775 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000776 }
Roland McGrath02203312007-06-11 22:06:31 +0000777 }
Roland McGrath02203312007-06-11 22:06:31 +0000778
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200779 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000780 uid_t run_euid = run_uid;
781 gid_t run_egid = run_gid;
782
783 if (statbuf.st_mode & S_ISUID)
784 run_euid = statbuf.st_uid;
785 if (statbuf.st_mode & S_ISGID)
786 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000787 /*
788 * It is important to set groups before we
789 * lose privileges on setuid.
790 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200791 if (initgroups(username, run_gid) < 0) {
792 perror_msg_and_die("initgroups");
793 }
794 if (setregid(run_gid, run_egid) < 0) {
795 perror_msg_and_die("setregid");
796 }
797 if (setreuid(run_uid, run_euid) < 0) {
798 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000799 }
800 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200801 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000802 setreuid(run_uid, run_uid);
803
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000804 if (!daemonized_tracer) {
805 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200806 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000807 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200808 * the immediately following execve syscall.
809 * Can't do this on NOMMU systems, we are after
810 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000811 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400812 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200813 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000814 } else {
815 struct sigaction sv_sigchld;
816 sigaction(SIGCHLD, NULL, &sv_sigchld);
817 /*
818 * Make sure it is not SIG_IGN, otherwise wait
819 * will not block.
820 */
821 signal(SIGCHLD, SIG_DFL);
822 /*
823 * Wait for grandchild to attach to us.
824 * It kills child after that, and wait() unblocks.
825 */
826 alarm(3);
827 wait(NULL);
828 alarm(0);
829 sigaction(SIGCHLD, &sv_sigchld, NULL);
830 }
Roland McGrath02203312007-06-11 22:06:31 +0000831
832 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200833 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000834 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000835
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200836 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200837
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200838 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100839 if (!use_seize) {
840 /* child did PTRACE_TRACEME, nothing to do in parent */
841 } else {
842 if (!strace_vforked) {
843 /* Wait until child stopped itself */
844 int status;
845 while (waitpid(pid, &status, WSTOPPED) < 0) {
846 if (errno == EINTR)
847 continue;
848 perror_msg_and_die("waitpid");
849 }
850 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100851 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100852 perror_msg_and_die("Unexpected wait status %x", status);
853 }
854 }
855 /* Else: vforked case, we have no way to sync.
856 * Just attach to it as soon as possible.
857 * This means that we may miss a few first syscalls...
858 */
859
860 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100861 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100862 perror_msg_and_die("Can't attach to %d", pid);
863 }
864 if (!strace_vforked)
865 kill(pid, SIGCONT);
866 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200867 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200868 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100869 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200870 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100871 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200872 }
873 else {
874 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
875 strace_tracer_pid = getpid();
876 /* The tracee is our parent: */
877 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100878 alloctcb(pid);
879 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000880 }
Roland McGrath02203312007-06-11 22:06:31 +0000881}
882
Wang Chaob13c0de2010-11-12 17:25:19 +0800883/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000884 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800885 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000886 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800887 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000888static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200889test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800890{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000891 int pid, expected_grandchild = 0, found_grandchild = 0;
892 const unsigned int test_options = PTRACE_O_TRACECLONE |
893 PTRACE_O_TRACEFORK |
894 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800895
Denys Vlasenko5d645812011-08-20 12:48:18 +0200896 pid = fork();
897 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000898 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200899 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000900 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100901 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000902 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
903 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100904 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000905 if (fork() < 0)
906 perror_msg_and_die("fork");
907 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800908 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000909
910 while (1) {
911 int status, tracee_pid;
912
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000913 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000914 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000915 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000916 if (errno == EINTR)
917 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100918 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000919 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000920 kill_save_errno(pid, SIGKILL);
921 perror_msg_and_die("%s: unexpected wait result %d",
922 __func__, tracee_pid);
923 }
924 if (WIFEXITED(status)) {
925 if (WEXITSTATUS(status)) {
926 if (tracee_pid != pid)
927 kill_save_errno(pid, SIGKILL);
928 error_msg_and_die("%s: unexpected exit status %u",
929 __func__, WEXITSTATUS(status));
930 }
931 continue;
932 }
933 if (WIFSIGNALED(status)) {
934 if (tracee_pid != pid)
935 kill_save_errno(pid, SIGKILL);
936 error_msg_and_die("%s: unexpected signal %u",
937 __func__, WTERMSIG(status));
938 }
939 if (!WIFSTOPPED(status)) {
940 if (tracee_pid != pid)
941 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100942 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000943 error_msg_and_die("%s: unexpected wait status %x",
944 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000945 }
946 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000947 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000948 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
949 kill_save_errno(tracee_pid, SIGKILL);
950 kill_save_errno(pid, SIGKILL);
951 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800952 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000953 continue;
954 }
955 switch (WSTOPSIG(status)) {
956 case SIGSTOP:
957 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
958 && errno != EINVAL && errno != EIO)
959 perror_msg("PTRACE_SETOPTIONS");
960 break;
961 case SIGTRAP:
962 if (status >> 16 == PTRACE_EVENT_FORK) {
963 long msg = 0;
964
965 if (ptrace(PTRACE_GETEVENTMSG, pid,
966 NULL, (long) &msg) == 0)
967 expected_grandchild = msg;
968 }
969 break;
970 }
971 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
972 kill_save_errno(pid, SIGKILL);
973 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800974 }
975 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000976 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200977 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000978 if (debug)
979 fprintf(stderr, "ptrace_setoptions = %#x\n",
980 ptrace_setoptions);
981 return;
982 }
983 error_msg("Test for PTRACE_O_TRACECLONE failed, "
984 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800985}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200986
987/*
988 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
989 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
990 * and then see whether it will stop with (SIGTRAP | 0x80).
991 *
992 * Use of this option enables correct handling of user-generated SIGTRAPs,
993 * and SIGTRAPs generated by special instructions such as int3 on x86:
994 * _start: .globl _start
995 * int3
996 * movl $42, %ebx
997 * movl $1, %eax
998 * int $0x80
999 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
1000 */
1001static void
1002test_ptrace_setoptions_for_all(void)
1003{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001004 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1005 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001006 int pid;
1007 int it_worked = 0;
1008
1009 pid = fork();
1010 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001011 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001012
1013 if (pid == 0) {
1014 pid = getpid();
1015 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001016 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001017 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1018 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001019 kill(pid, SIGSTOP);
1020 _exit(0); /* parent should see entry into this syscall */
1021 }
1022
1023 while (1) {
1024 int status, tracee_pid;
1025
1026 errno = 0;
1027 tracee_pid = wait(&status);
1028 if (tracee_pid <= 0) {
1029 if (errno == EINTR)
1030 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001031 kill_save_errno(pid, SIGKILL);
1032 perror_msg_and_die("%s: unexpected wait result %d",
1033 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001034 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001035 if (WIFEXITED(status)) {
1036 if (WEXITSTATUS(status) == 0)
1037 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001038 error_msg_and_die("%s: unexpected exit status %u",
1039 __func__, WEXITSTATUS(status));
1040 }
1041 if (WIFSIGNALED(status)) {
1042 error_msg_and_die("%s: unexpected signal %u",
1043 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001044 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001045 if (!WIFSTOPPED(status)) {
1046 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001047 error_msg_and_die("%s: unexpected wait status %x",
1048 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001049 }
1050 if (WSTOPSIG(status) == SIGSTOP) {
1051 /*
1052 * We don't check "options aren't accepted" error.
1053 * If it happens, we'll never get (SIGTRAP | 0x80),
1054 * and thus will decide to not use the option.
1055 * IOW: the outcome of the test will be correct.
1056 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001057 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1058 && errno != EINVAL && errno != EIO)
1059 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001060 }
1061 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1062 it_worked = 1;
1063 }
1064 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001065 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001066 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001067 }
1068 }
1069
1070 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001071 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001072 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001073 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001074 fprintf(stderr, "ptrace_setoptions = %#x\n",
1075 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001076 return;
1077 }
1078
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001079 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1080 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001081}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001082
1083# ifdef USE_SEIZE
1084static void
1085test_ptrace_seize(void)
1086{
1087 int pid;
1088
1089 pid = fork();
1090 if (pid < 0)
1091 perror_msg_and_die("fork");
1092
1093 if (pid == 0) {
1094 pause();
1095 _exit(0);
1096 }
1097
1098 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1099 * attaching tracee continues to run unless a trap condition occurs.
1100 * PTRACE_SEIZE doesn't affect signal or group stop state.
1101 */
1102 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1103 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1104 } else if (debug) {
1105 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1106 }
1107
1108 kill(pid, SIGKILL);
1109
1110 while (1) {
1111 int status, tracee_pid;
1112
1113 errno = 0;
1114 tracee_pid = waitpid(pid, &status, 0);
1115 if (tracee_pid <= 0) {
1116 if (errno == EINTR)
1117 continue;
1118 perror_msg_and_die("%s: unexpected wait result %d",
1119 __func__, tracee_pid);
1120 }
1121 if (WIFSIGNALED(status)) {
1122 return;
1123 }
1124 error_msg_and_die("%s: unexpected wait status %x",
1125 __func__, status);
1126 }
1127}
1128# else /* !USE_SEIZE */
1129# define test_ptrace_seize() ((void)0)
1130# endif
1131
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001132static void
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001133get_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
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001143/*
1144 * Initialization part of main() was eating much stack (~0.5k),
1145 * which was unused after init.
1146 * We can reuse it if we move init code into a separate function.
1147 *
1148 * Don't want main() to inline us and defeat the reason
1149 * we have a separate function.
1150 */
1151static void __attribute__ ((noinline))
1152init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001155 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001156 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 struct sigaction sa;
1158
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001159 progname = argv[0] ? argv[0] : "strace";
1160
Denys Vlasenko75422762011-05-27 14:36:01 +02001161 strace_tracer_pid = getpid();
1162
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001163 get_os_release();
1164
Roland McGrathee9d4352002-12-18 04:16:10 +00001165 /* Allocate the initial tcbtab. */
1166 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001167 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001168 if (!tcbtab)
1169 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001170 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001171 if (!tcp)
1172 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001173 for (c = 0; c < tcbtabsize; c++)
1174 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001175
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001177 set_sortby(DEFAULT_SORTBY);
1178 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179 qualify("trace=all");
1180 qualify("abbrev=all");
1181 qualify("verbose=all");
1182 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001184 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001185 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001186 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 switch (c) {
1188 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001189 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001190 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001191 }
1192 cflag = CFLAG_ONLY_STATS;
1193 break;
1194 case 'C':
1195 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001196 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001197 }
1198 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 break;
1200 case 'd':
1201 debug++;
1202 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001203 case 'D':
1204 daemonized_tracer = 1;
1205 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001206 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001207 optF = 1;
1208 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209 case 'f':
1210 followfork++;
1211 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 case 'h':
1213 usage(stdout, 0);
1214 break;
1215 case 'i':
1216 iflag++;
1217 break;
1218 case 'q':
1219 qflag++;
1220 break;
1221 case 'r':
1222 rflag++;
1223 tflag++;
1224 break;
1225 case 't':
1226 tflag++;
1227 break;
1228 case 'T':
1229 dtime++;
1230 break;
1231 case 'x':
1232 xflag++;
1233 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001234 case 'y':
1235 show_fd_path = 1;
1236 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 case 'v':
1238 qualify("abbrev=none");
1239 break;
1240 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001241 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 exit(0);
1243 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001244 case 'z':
1245 not_failing_only = 1;
1246 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247 case 'a':
1248 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001249 if (acolumn < 0)
1250 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 break;
1252 case 'e':
1253 qualify(optarg);
1254 break;
1255 case 'o':
1256 outfname = strdup(optarg);
1257 break;
1258 case 'O':
1259 set_overhead(atoi(optarg));
1260 break;
1261 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001262 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001263 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001264 case 'P':
1265 tracing_paths = 1;
1266 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001267 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001268 }
1269 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001270 case 's':
1271 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001272 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001273 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001274 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001275 break;
1276 case 'S':
1277 set_sortby(optarg);
1278 break;
1279 case 'u':
1280 username = strdup(optarg);
1281 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001282 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001283 if (putenv(optarg) < 0)
1284 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001285 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001286 case 'I':
1287 opt_intr = atoi(optarg);
1288 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1289 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1290 }
1291 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001292 default:
1293 usage(stderr, 1);
1294 break;
1295 }
1296 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001297 argv += optind;
1298 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001299
Denys Vlasenko102ec492011-08-25 01:27:59 +02001300 acolumn_spaces = malloc(acolumn + 1);
1301 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001302 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001303 memset(acolumn_spaces, ' ', acolumn);
1304 acolumn_spaces[acolumn] = '\0';
1305
Denys Vlasenko837399a2012-01-24 11:37:03 +01001306 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001307 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001308 usage(stderr, 1);
1309
Denys Vlasenkofd883382012-03-09 13:03:41 +01001310 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001311 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001312 }
1313
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001314 if (!followfork)
1315 followfork = optF;
1316
Roland McGrathcb9def62006-04-25 07:48:03 +00001317 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001318 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001319 }
1320
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321 /* See if they want to run as another user. */
1322 if (username != NULL) {
1323 struct passwd *pent;
1324
1325 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001326 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001328 pent = getpwnam(username);
1329 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001330 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 }
1332 run_uid = pent->pw_uid;
1333 run_gid = pent->pw_gid;
1334 }
1335 else {
1336 run_uid = getuid();
1337 run_gid = getgid();
1338 }
1339
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001340 if (followfork)
1341 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001342 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001343 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001344
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345 /* Check if they want to redirect the output. */
1346 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001347 /* See if they want to pipe the output. */
1348 if (outfname[0] == '|' || outfname[0] == '!') {
1349 /*
1350 * We can't do the <outfname>.PID funny business
1351 * when using popen, so prohibit it.
1352 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001353 if (followfork > 1)
1354 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1355 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001356 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001357 else if (followfork <= 1)
1358 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001359 }
1360
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001361 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001362 char *buf = malloc(BUFSIZ);
1363 if (!buf)
1364 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001365 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001366 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001367 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001368 if (!opt_intr)
1369 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001370 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001371 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001372 if (!opt_intr)
1373 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001374
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001375 /* argv[0] -pPID -oFILE Default interactive setting
1376 * yes 0 0 INTR_WHILE_WAIT
1377 * no 1 0 INTR_WHILE_WAIT
1378 * yes 0 1 INTR_NEVER
1379 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001380 */
1381
1382 /* STARTUP_CHILD must be called before the signal handlers get
1383 installed below as they are inherited into the spawned process.
1384 Also we do not need to be protected by them as during interruption
1385 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001386 if (argv[0])
1387 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389 sigemptyset(&empty_set);
1390 sigemptyset(&blocked_set);
1391 sa.sa_handler = SIG_IGN;
1392 sigemptyset(&sa.sa_mask);
1393 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001394 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1395 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1396 if (opt_intr != INTR_ANYWHERE) {
1397 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1398 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1399 /*
1400 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1401 * fatal signals are blocked while syscall stop is processed,
1402 * and acted on in between, when waiting for new syscall stops.
1403 * In non-interactive mode, signals are ignored.
1404 */
1405 if (opt_intr == INTR_WHILE_WAIT) {
1406 sigaddset(&blocked_set, SIGHUP);
1407 sigaddset(&blocked_set, SIGINT);
1408 sigaddset(&blocked_set, SIGQUIT);
1409 sigaddset(&blocked_set, SIGPIPE);
1410 sigaddset(&blocked_set, SIGTERM);
1411 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001412 }
1413 /* SIG_IGN, or set handler for these */
1414 sigaction(SIGHUP, &sa, NULL);
1415 sigaction(SIGINT, &sa, NULL);
1416 sigaction(SIGQUIT, &sa, NULL);
1417 sigaction(SIGPIPE, &sa, NULL);
1418 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001419 }
Roland McGrath553a6092002-12-16 20:40:39 +00001420 /* Make sure SIGCHLD has the default action so that waitpid
1421 definitely works without losing track of children. The user
1422 should not have given us a bogus state to inherit, but he might
1423 have. Arguably we should detect SIG_IGN here and pass it on
1424 to children, but probably noone really needs that. */
1425 sa.sa_handler = SIG_DFL;
1426 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427
Denys Vlasenkofd883382012-03-09 13:03:41 +01001428 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001429 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001430
Denys Vlasenkofd883382012-03-09 13:03:41 +01001431 /* Do we want pids printed in our -o OUTFILE?
1432 * -ff: no (every pid has its own file); or
1433 * -f: yes (there can be more pids in the future); or
1434 * -p PID1,PID2: yes (there are already more than one pid)
1435 */
1436 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437}
1438
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001439static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001440expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001441{
1442 /* Allocate some more TCBs and expand the table.
1443 We don't want to relocate the TCBs because our
1444 callers have pointers and it would be a pain.
1445 So tcbtab is a table of pointers. Since we never
1446 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001447 int i = tcbtabsize;
1448 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1449 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001450 if (!newtab || !newtcbs)
1451 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001452 tcbtabsize *= 2;
1453 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001454 while (i < tcbtabsize)
1455 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001456}
1457
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001459alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460{
1461 int i;
1462 struct tcb *tcp;
1463
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001464 if (nprocs == tcbtabsize)
1465 expand_tcbtab();
1466
Roland McGrathee9d4352002-12-18 04:16:10 +00001467 for (i = 0; i < tcbtabsize; i++) {
1468 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001470 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001471 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001472 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001474#if SUPPORTED_PERSONALITIES > 1
1475 tcp->currpers = current_personality;
1476#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001478 if (debug)
1479 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001480 if (command_options_parsed)
1481 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 return tcp;
1483 }
1484 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001485 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001486}
1487
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001488static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001489pid2tcb(int pid)
1490{
1491 int i;
1492
1493 if (pid <= 0)
1494 return NULL;
1495
1496 for (i = 0; i < tcbtabsize; i++) {
1497 struct tcb *tcp = tcbtab[i];
1498 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1499 return tcp;
1500 }
1501
1502 return NULL;
1503}
1504
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505void
Denys Vlasenko12014262011-05-30 14:00:14 +02001506droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507{
1508 if (tcp->pid == 0)
1509 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001510
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001512 if (debug)
1513 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001514
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001515 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001516 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001517
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001518 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519}
1520
Roland McGrath0a463882007-07-05 18:43:16 +00001521/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001522 * Never call DETACH twice on the same process as both unattached and
1523 * attached-unstopped processes give the same ESRCH. For unattached process we
1524 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1525 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001527detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001529 int error;
1530 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
1532 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001533 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535 /*
1536 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001537 * before detaching. Arghh. We go through hoops
1538 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001540#if defined(SPARC)
1541#undef PTRACE_DETACH
1542#define PTRACE_DETACH PTRACE_SUNDETACH
1543#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001544
1545 sigstop_expected = 0;
1546 if (tcp->flags & TCB_ATTACHED) {
1547 /*
1548 * We attached but possibly didn't see the expected SIGSTOP.
1549 * We must catch exactly one as otherwise the detached process
1550 * would be left stopped (process state T).
1551 */
1552 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1553 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1554 if (error == 0) {
1555 /* On a clear day, you can see forever. */
1556 }
1557 else if (errno != ESRCH) {
1558 /* Shouldn't happen. */
1559 perror("detach: ptrace(PTRACE_DETACH, ...)");
1560 }
1561 else if (my_tkill(tcp->pid, 0) < 0) {
1562 if (errno != ESRCH)
1563 perror("detach: checking sanity");
1564 }
1565 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1566 if (errno != ESRCH)
1567 perror("detach: stopping child");
1568 }
1569 else
1570 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001571 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001572
1573 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001575#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001576 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001577 if (errno == ECHILD) /* Already gone. */
1578 break;
1579 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001580 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001581 break;
1582 }
1583#endif /* __WALL */
1584 /* No __WALL here. */
1585 if (waitpid(tcp->pid, &status, 0) < 0) {
1586 if (errno != ECHILD) {
1587 perror("detach: waiting");
1588 break;
1589 }
1590#ifdef __WCLONE
1591 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001592 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001593 if (errno != ECHILD)
1594 perror("detach: waiting");
1595 break;
1596 }
1597#endif /* __WCLONE */
1598 }
1599#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001600 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001601#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602 if (!WIFSTOPPED(status)) {
1603 /* Au revoir, mon ami. */
1604 break;
1605 }
1606 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001607 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001608 break;
1609 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001610 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001611 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001612 : WSTOPSIG(status));
1613 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001616 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001618 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619 fprintf(stderr, "Process %u detached\n", tcp->pid);
1620
1621 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001622
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 return error;
1624}
1625
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001627cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628{
1629 int i;
1630 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001631 int fatal_sig;
1632
1633 /* 'interrupted' is a volatile object, fetch it only once */
1634 fatal_sig = interrupted;
1635 if (!fatal_sig)
1636 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637
Roland McGrathee9d4352002-12-18 04:16:10 +00001638 for (i = 0; i < tcbtabsize; i++) {
1639 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 if (!(tcp->flags & TCB_INUSE))
1641 continue;
1642 if (debug)
1643 fprintf(stderr,
1644 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001645 if (printing_tcp &&
1646 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1647 tprints(" <unfinished ...>\n");
1648 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001650 if (!(tcp->flags & TCB_STRACE_CHILD))
Denys Vlasenko4c196382012-01-04 15:11:09 +01001651 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652 else {
1653 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001654 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 }
1656 }
1657 if (cflag)
1658 call_summary(outf);
1659}
1660
1661static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001662interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001664 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665}
1666
1667#ifndef HAVE_STRERROR
1668
Roland McGrath6d2b3492002-12-30 00:51:30 +00001669#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670extern int sys_nerr;
1671extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001672#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673
1674const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001675strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001677 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001679 if (err_no < 1 || err_no >= sys_nerr) {
1680 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001681 return buf;
1682 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001683 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684}
1685
1686#endif /* HAVE_STERRROR */
1687
1688#ifndef HAVE_STRSIGNAL
1689
Roland McGrath8f474e02003-01-14 07:53:33 +00001690#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001691extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001693#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1694extern char *_sys_siglist[];
1695#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696
1697const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001698strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001700 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701
1702 if (sig < 1 || sig >= NSIG) {
1703 sprintf(buf, "Unknown signal %d", sig);
1704 return buf;
1705 }
1706#ifdef HAVE__SYS_SIGLIST
1707 return _sys_siglist[sig];
1708#else
1709 return sys_siglist[sig];
1710#endif
1711}
1712
1713#endif /* HAVE_STRSIGNAL */
1714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001716trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001719 struct rusage *rup = cflag ? &ru : NULL;
1720# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001721 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001722# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723
Roland McGratheb9e2e82009-06-02 16:49:22 -07001724 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001725 int pid;
1726 int wait_errno;
1727 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001728 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001729 struct tcb *tcp;
1730 unsigned event;
1731
Denys Vlasenko222713a2009-03-17 14:29:59 +00001732 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001733 return 0;
1734 if (interactive)
1735 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001736# ifdef __WALL
1737 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001738 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001739 /* this kernel does not support __WALL */
1740 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001741 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001742 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001743 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001744 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001745 pid = wait4(-1, &status, __WCLONE, rup);
1746 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001747 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001748 }
1749 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001750# else
1751 pid = wait4(-1, &status, 0, rup);
1752# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001754 if (interactive)
1755 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001757 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001758 switch (wait_errno) {
1759 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001761 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 /*
1763 * We would like to verify this case
1764 * but sometimes a race in Solbourne's
1765 * version of SunOS sometimes reports
1766 * ECHILD before sending us SIGCHILD.
1767 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001768 return 0;
1769 default:
1770 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001771 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001772 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 }
1774 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001775 if (pid == popen_pid) {
1776 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001777 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001778 continue;
1779 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001780
1781 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001782 if (debug) {
1783 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001784 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001785 static const char *const event_names[] = {
1786 [PTRACE_EVENT_CLONE] = "CLONE",
1787 [PTRACE_EVENT_FORK] = "FORK",
1788 [PTRACE_EVENT_VFORK] = "VFORK",
1789 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1790 [PTRACE_EVENT_EXEC] = "EXEC",
1791 [PTRACE_EVENT_EXIT] = "EXIT",
1792 };
1793 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001794 if (event < ARRAY_SIZE(event_names))
1795 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001796 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001797 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001798 e = buf;
1799 }
1800 fprintf(stderr, " PTRACE_EVENT_%s", e);
1801 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001802 strcpy(buf, "???");
1803 if (WIFSIGNALED(status))
1804#ifdef WCOREDUMP
1805 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1806 WCOREDUMP(status) ? "core," : "",
1807 signame(WTERMSIG(status)));
1808#else
1809 sprintf(buf, "WIFSIGNALED,sig=%s",
1810 signame(WTERMSIG(status)));
1811#endif
1812 if (WIFEXITED(status))
1813 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1814 if (WIFSTOPPED(status))
1815 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001816#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001817 if (WIFCONTINUED(status))
1818 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001819#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001820 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1821 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001823 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001824 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001825
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001826 /* Under Linux, execve changes pid to thread leader's pid,
1827 * and we see this changed pid on EVENT_EXEC and later,
1828 * execve sysexit. Leader "disappears" without exit
1829 * notification. Let user know that, drop leader's tcb,
1830 * and fix up pid in execve thread's tcb.
1831 * Effectively, execve thread's tcb replaces leader's tcb.
1832 *
1833 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1834 * on exit syscall) in multithreaded programs exactly
1835 * in order to handle this case.
1836 *
1837 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1838 * On 2.6 and earlier, it can return garbage.
1839 */
1840 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1841 long old_pid = 0;
1842 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1843 && old_pid > 0
1844 && old_pid != pid
1845 ) {
1846 struct tcb *execve_thread = pid2tcb(old_pid);
1847 if (tcp) {
1848 outf = tcp->outf;
1849 curcol = tcp->curcol;
1850 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001851 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001852 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001853 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001854 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1855 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001856 fflush(outf);
1857 }
1858 if (execve_thread) {
1859 /* swap output FILEs (needed for -ff) */
1860 tcp->outf = execve_thread->outf;
1861 execve_thread->outf = outf;
1862 }
1863 droptcb(tcp);
1864 }
1865 tcp = execve_thread;
1866 if (tcp) {
1867 tcp->pid = pid;
1868 tcp->flags |= TCB_REPRINT;
1869 }
1870 }
1871 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001872
Denys Vlasenko5d645812011-08-20 12:48:18 +02001873 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001874 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001875 /* This is needed to go with the CLONE_PTRACE
1876 changes in process.c/util.c: we might see
1877 the child's initial trap before we see the
1878 parent return from the clone syscall.
1879 Leave the child suspended until the parent
1880 returns from its system call. Only then
1881 will we have the association of parent and
1882 child so that we know how to do clearbpt
1883 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001884 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001885 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001886 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001887 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001888 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001889 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001890 else
1891 /* This can happen if a clone call used
1892 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001893 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001894 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001895 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001896 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001897 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001898 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001899 /* set current output file */
1900 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001901 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001902 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001903 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1904 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001906
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001907 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001908 if (pid == strace_child)
1909 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001910 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001911 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1912 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001913#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001914 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001915 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001916 WCOREDUMP(status) ? "(core dumped) " : "");
1917#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001918 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001919 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001920#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001921 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001923 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001924 droptcb(tcp);
1925 continue;
1926 }
1927 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001928 if (pid == strace_child)
1929 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001930 if (tcp == printing_tcp) {
1931 tprints(" <unfinished ...>\n");
1932 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001933 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001934 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1935 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001936 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1937 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001938 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001939 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 droptcb(tcp);
1941 continue;
1942 }
1943 if (!WIFSTOPPED(status)) {
1944 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1945 droptcb(tcp);
1946 continue;
1947 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001948
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001949 /* Is this the very first time we see this tracee stopped? */
1950 if (tcp->flags & TCB_STARTUP) {
1951 if (debug)
1952 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001954 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001955 /*
1956 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001957 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001958 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001959 if (clearbpt(tcp) < 0) {
1960 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001961 droptcb(tcp);
1962 cleanup();
1963 return -1;
1964 }
1965 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001966 if (ptrace_setoptions) {
1967 if (debug)
1968 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1969 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1970 if (errno != ESRCH) {
1971 /* Should never happen, really */
1972 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001973 }
1974 }
1975 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001976 }
1977
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001978 sig = WSTOPSIG(status);
1979
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001980 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001981 /* Ptrace event */
1982#ifdef USE_SEIZE
1983 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001984 /*
1985 * PTRACE_INTERRUPT-stop or group-stop.
1986 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1987 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001988 if (sig == SIGSTOP
1989 || sig == SIGTSTP
1990 || sig == SIGTTIN
1991 || sig == SIGTTOU
1992 ) {
1993 stopped = 1;
1994 goto show_stopsig;
1995 }
1996 }
1997#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001998 goto restart_tracee_with_sig_0;
1999 }
2000
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002001 /* Is this post-attach SIGSTOP?
2002 * Interestingly, the process may stop
2003 * with STOPSIG equal to some other signal
2004 * than SIGSTOP if we happend to attach
2005 * just before the process takes a signal.
2006 */
2007 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2008 if (debug)
2009 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2010 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002011 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012 }
2013
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002014 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002015 siginfo_t si;
2016
2017 /* Nonzero (true) if tracee is stopped by signal
2018 * (as opposed to "tracee received signal").
2019 */
2020 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002021#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002022 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002023#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002024 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002025 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002026#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002027 long pc = 0;
2028 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002029
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002030 upeek(tcp, PT_CR_IPSR, &psr);
2031 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002032
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002033# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002034 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002035# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002036# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002037#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002038# define PC_FORMAT_STR ""
2039# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002040#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002041 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002042 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002043 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002044 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002045 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002046 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002047 PC_FORMAT_ARG);
2048 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002049 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002050 strsignal(sig),
2051 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002052 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002053 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002054 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002056
2057 if (!stopped)
2058 /* It's signal-delivery-stop. Inject the signal */
2059 goto restart_tracee;
2060
2061 /* It's group-stop */
2062#ifdef USE_SEIZE
2063 if (use_seize) {
2064 /*
2065 * This ends ptrace-stop, but does *not* end group-stop.
2066 * This makes stopping signals work properly on straced process
2067 * (that is, process really stops. It used to continue to run).
2068 */
2069 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2070 cleanup();
2071 return -1;
2072 }
2073 continue;
2074 }
2075 /* We don't have PTRACE_LISTEN support... */
2076#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002077 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002078 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002079
2080 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002081 if (interrupted)
2082 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002083
2084 /* This should be syscall entry or exit.
2085 * (Or it still can be that pesky post-execve SIGTRAP!)
2086 * Handle it.
2087 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002088 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2089 /* ptrace() failed in trace_syscall() with ESRCH.
2090 * Likely a result of process disappearing mid-flight.
2091 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002092 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002093 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002094 if (printing_tcp) {
2095 /* Do we have dangling line "syscall(param, param"?
2096 * Finish the line then.
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002097 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002098 printing_tcp->flags |= TCB_REPRINT;
2099 tprints(" <unfinished ...>\n");
2100 printing_tcp = NULL;
2101 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002102 }
Denys Vlasenkof2025022012-03-09 15:29:45 +01002103 /* We assume that ptrace error was caused by process death.
2104 * We used to detach(tcp) here, but since we no longer
2105 * implement "detach before death" policy/hack,
2106 * we can let this process to report its death to us
2107 * normally, via WIFEXITED or WIFSIGNALED wait status.
2108 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002109 continue;
2110 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002111 restart_tracee_with_sig_0:
2112 sig = 0;
2113 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002114 /* Remember current print column before continuing. */
2115 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002116 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002117 cleanup();
2118 return -1;
2119 }
2120 }
2121 return 0;
2122}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002123
2124int
2125main(int argc, char *argv[])
2126{
2127 init(argc, argv);
2128
2129 /* Run main tracing loop */
2130 if (trace() < 0)
2131 return 1;
2132
2133 cleanup();
2134 fflush(NULL);
2135 if (exit_code > 0xff) {
2136 /* Avoid potential core file clobbering. */
2137 struct rlimit rlim = {0, 0};
2138 setrlimit(RLIMIT_CORE, &rlim);
2139
2140 /* Child was killed by a signal, mimic that. */
2141 exit_code &= 0xff;
2142 signal(exit_code, SIG_DFL);
2143 raise(exit_code);
2144 /* Paranoia - what if this signal is not fatal?
2145 Exit with 128 + signo then. */
2146 exit_code += 128;
2147 }
2148
2149 return exit_code;
2150}