blob: a17adb394f5da887cfd2e1f24e47277118ab0135 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00006 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#include "defs.h"
34
Roland McGrath795edb12005-02-02 04:44:57 +000035#include <sys/types.h>
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020036#include <stdarg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037#include <signal.h>
38#include <errno.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#include <sys/resource.h>
42#include <sys/wait.h>
43#include <sys/stat.h>
44#include <pwd.h>
45#include <grp.h>
46#include <string.h>
Roland McGrath70b08532004-04-09 00:25:21 +000047#include <dirent.h>
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +010048#include <sys/utsname.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049
Roland McGrath134813a2007-06-02 00:07:33 +000050# include <asm/unistd.h>
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020051# if defined __NR_tkill
52# define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000053# else
54 /* kill() may choose arbitrarily the target task of the process group
55 while we later wait on a that specific TID. PID process waits become
56 TID task specific waits for a process under ptrace(2). */
57# warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
Denys Vlasenko44f87ef2011-08-17 15:18:21 +020058# define my_tkill(tid, sig) kill((tid), (sig))
Roland McGrath134813a2007-06-02 00:07:33 +000059# endif
Roland McGrath134813a2007-06-02 00:07:33 +000060
Denys Vlasenko84703742012-02-25 02:38:52 +010061#if defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +000062# include <asm/ptrace_offsets.h>
63#endif
64
Denys Vlasenko96d5a762008-12-29 19:13:27 +000065extern char **environ;
Denys Vlasenko418d66a2009-01-17 01:52:54 +000066extern int optind;
67extern char *optarg;
Denys Vlasenko96d5a762008-12-29 19:13:27 +000068
Roland McGrath41c48222008-07-18 00:25:10 +000069int debug = 0, followfork = 0;
Denys Vlasenkof44cce42011-06-21 14:34:10 +020070unsigned int ptrace_setoptions = 0;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +020071/* Which WSTOPSIG(status) value marks syscall traps? */
Denys Vlasenko75422762011-05-27 14:36:01 +020072static unsigned int syscall_trap_sig = SIGTRAP;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +000073int dtime = 0, xflag = 0, qflag = 0;
74cflag_t cflag = CFLAG_NONE;
Denys Vlasenkofd883382012-03-09 13:03:41 +010075static int iflag = 0, rflag = 0, tflag = 0;
76static int print_pid_pfx = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +010077
78/* -I n */
79enum {
80 INTR_NOT_SET = 0,
81 INTR_ANYWHERE = 1, /* don't block/ignore any signals */
82 INTR_WHILE_WAIT = 2, /* block fatal signals while decoding syscall. default */
83 INTR_NEVER = 3, /* block fatal signals. default if '-o FILE PROG' */
84 INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
85 NUM_INTR_OPTS
86};
87static int opt_intr;
88/* We play with signal mask only if this mode is active: */
89#define interactive (opt_intr == INTR_WHILE_WAIT)
90
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +000091/*
92 * daemonized_tracer supports -D option.
93 * With this option, strace forks twice.
94 * Unlike normal case, with -D *grandparent* process exec's,
95 * becoming a traced process. Child exits (this prevents traced process
96 * from having children it doesn't expect to have), and grandchild
97 * attaches to grandparent similarly to strace -p PID.
98 * This allows for more transparent interaction in cases
99 * when process and its parent are communicating via signals,
100 * wait() etc. Without -D, strace process gets lodged in between,
101 * disrupting parent<->child link.
102 */
103static bool daemonized_tracer = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100105#ifdef USE_SEIZE
106static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
107# define use_seize (post_attach_sigstop == 0)
108#else
109# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
110# define use_seize 0
111#endif
112
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000113/* Sometimes we want to print only succeeding syscalls. */
114int not_failing_only = 0;
115
Grant Edwards8a082772011-04-07 20:25:40 +0000116/* Show path associated with fd arguments */
117int show_fd_path = 0;
118
119/* are we filtering traces based on paths? */
120int tracing_paths = 0;
121
Dmitry V. Levina6809652008-11-10 17:14:58 +0000122static int exit_code = 0;
123static int strace_child = 0;
Denys Vlasenko75422762011-05-27 14:36:01 +0200124static int strace_tracer_pid = 0;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700125
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000126static char *username = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200127static uid_t run_uid;
128static gid_t run_gid;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130int max_strlen = DEFAULT_STRLEN;
Denys Vlasenko102ec492011-08-25 01:27:59 +0200131static int acolumn = DEFAULT_ACOLUMN;
132static char *acolumn_spaces;
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +0000133static char *outfname = NULL;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200134static FILE *outf;
Denys Vlasenko000b6012012-01-28 01:25:03 +0100135struct tcb *printing_tcp = NULL;
Andreas Schwabccdff482009-10-27 16:27:13 +0100136static int curcol;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200137static struct tcb **tcbtab;
Denys Vlasenko2b60c352011-06-22 12:45:25 +0200138static unsigned int nprocs, tcbtabsize;
Denys Vlasenkoead73bd2011-06-24 22:49:58 +0200139static const char *progname;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +0100141static char *os_release; /* from uname() */
142
Denys Vlasenko4c196382012-01-04 15:11:09 +0100143static int detach(struct tcb *tcp);
Andreas Schwabe5355de2009-10-27 16:56:43 +0100144static int trace(void);
145static void cleanup(void);
146static void interrupt(int sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147static sigset_t empty_set, blocked_set;
148
149#ifdef HAVE_SIG_ATOMIC_T
150static volatile sig_atomic_t interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100151#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152static volatile int interrupted;
Denys Vlasenkoa3559252012-01-29 16:43:51 +0100153#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155static void
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200156usage(FILE *ofp, int exitval)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157{
158 fprintf(ofp, "\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100159usage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
160 [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100161 [-P path] [PROG [ARGS]]\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100162 or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100163 [PROG [ARGS]]\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164-c -- count time, calls, and errors for each syscall and report summary\n\
Andreas Schwabb87d30c2010-06-11 15:49:36 +0200165-C -- like -c but also print regular output while processes are running\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100166-D -- run tracer process as a detached grandchild, not as parent\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167-f -- follow forks, -ff -- with output into separate files\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100168-F -- attempt to follow vforks\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169-i -- print instruction pointer at time of syscall\n\
Denys Vlasenkob51581e2012-01-29 16:53:03 +0100170-I interruptible\n\
171 1: no signals are blocked\n\
172 2: fatal signals are blocked while decoding syscall (default)\n\
173 3: fatal signals are always blocked (default if '-o FILE PROG')\n\
174 4: fatal signals and SIGTSTP (^Z) are always blocked\n\
175 (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176-q -- suppress messages about attaching, detaching, etc.\n\
177-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100178-T -- print time spent in each syscall\n\
179-v -- verbose mode: print unabbreviated argv, stat, termios, etc. args\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000181-y -- print paths associated with file descriptor arguments\n\
Denys Vlasenkocdab1be2012-02-03 12:17:57 +0100182-h -- print help message\n\
183-V -- print version\n\
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184-a column -- alignment COLUMN for printing syscall results (default %d)\n\
185-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
186 options: trace, abbrev, verbose, raw, signal, read, or write\n\
187-o file -- send trace output to FILE instead of stderr\n\
188-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
189-p pid -- trace process with process id PID, may be repeated\n\
190-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
191-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
192-u username -- run command as username handling setuid and/or setgid\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000193-E var=val -- put var=val in the environment for command\n\
194-E var -- remove var from the environment for command\n\
Grant Edwards8a082772011-04-07 20:25:40 +0000195-P path -- trace accesses to path\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000196" /* this is broken, so don't document it
Michal Ludvig17f8fb32002-11-06 13:17:21 +0000197-z -- print only succeeding syscalls\n\
Roland McGrathde6e5332003-01-24 04:31:23 +0000198 */
199, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 exit(exitval);
201}
202
Denys Vlasenko75422762011-05-27 14:36:01 +0200203static void die(void) __attribute__ ((noreturn));
204static void die(void)
205{
206 if (strace_tracer_pid == getpid()) {
207 cflag = 0;
208 cleanup();
209 }
210 exit(1);
211}
212
213static void verror_msg(int err_no, const char *fmt, va_list p)
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200214{
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100215 char *msg;
216
Dmitry V. Levin44d05322011-06-09 15:50:41 +0000217 fflush(NULL);
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100218
219 /* We want to print entire message with single fprintf to ensure
220 * message integrity if stderr is shared with other programs.
221 * Thus we use vasprintf + single fprintf.
222 */
223 msg = NULL;
Denys Vlasenkocfad5432012-01-24 12:48:02 +0100224 if (vasprintf(&msg, fmt, p) >= 0) {
Denys Vlasenko82bb78c2012-01-24 10:17:18 +0100225 if (err_no)
226 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
227 else
228 fprintf(stderr, "%s: %s\n", progname, msg);
229 free(msg);
230 } else {
231 /* malloc in vasprintf failed, try it without malloc */
232 fprintf(stderr, "%s: ", progname);
233 vfprintf(stderr, fmt, p);
234 if (err_no)
235 fprintf(stderr, ": %s\n", strerror(err_no));
236 else
237 putc('\n', stderr);
238 }
239 /* We don't switch stderr to buffered, thus fprintf(stderr)
240 * always flushes its output and this is not necessary: */
241 /* fflush(stderr); */
Denys Vlasenko75422762011-05-27 14:36:01 +0200242}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200243
Denys Vlasenko75422762011-05-27 14:36:01 +0200244void error_msg(const char *fmt, ...)
245{
246 va_list p;
247 va_start(p, fmt);
248 verror_msg(0, fmt, p);
249 va_end(p);
250}
251
252void error_msg_and_die(const char *fmt, ...)
253{
254 va_list p;
255 va_start(p, fmt);
256 verror_msg(0, fmt, p);
257 die();
258}
259
260void perror_msg(const char *fmt, ...)
261{
262 va_list p;
263 va_start(p, fmt);
264 verror_msg(errno, fmt, p);
265 va_end(p);
266}
267
268void perror_msg_and_die(const char *fmt, ...)
269{
270 va_list p;
271 va_start(p, fmt);
272 verror_msg(errno, fmt, p);
273 die();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200274}
275
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200276void die_out_of_memory(void)
277{
278 static bool recursed = 0;
279 if (recursed)
280 exit(1);
281 recursed = 1;
282 error_msg_and_die("Out of memory");
283}
284
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400285/* Glue for systems without a MMU that cannot provide fork() */
286#ifdef HAVE_FORK
287# define strace_vforked 0
288#else
289# define strace_vforked 1
290# define fork() vfork()
291#endif
292
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100293#ifdef USE_SEIZE
294static int
295ptrace_attach_or_seize(int pid)
296{
297 int r;
298 if (!use_seize)
299 return ptrace(PTRACE_ATTACH, pid, 0, 0);
300 r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
301 if (r)
302 return r;
303 r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
304 return r;
305}
306#else
307# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
308#endif
309
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200310static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000311set_cloexec_flag(int fd)
312{
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200313 int flags, newflags;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000314
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200315 flags = fcntl(fd, F_GETFD);
316 if (flags < 0) {
317 /* Can happen only if fd is bad.
318 * Should never happen: if it does, we have a bug
319 * in the caller. Therefore we just abort
320 * instead of propagating the error.
321 */
322 perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000323 }
324
325 newflags = flags | FD_CLOEXEC;
326 if (flags == newflags)
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200327 return;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000328
Denys Vlasenko1f532ab2011-06-22 13:11:23 +0200329 fcntl(fd, F_SETFD, newflags); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000330}
331
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100332static void kill_save_errno(pid_t pid, int sig)
333{
334 int saved_errno = errno;
335
336 (void) kill(pid, sig);
337 errno = saved_errno;
338}
339
Denys Vlasenko2e856a12012-03-12 23:02:26 +0100340void
341tprintf(const char *fmt, ...)
342{
343 va_list args;
344
345 va_start(args, fmt);
346 if (outf) {
347 int n = vfprintf(outf, fmt, args);
348 if (n < 0) {
349 if (outf != stderr)
350 perror(outfname == NULL
351 ? "<writing to pipe>" : outfname);
352 } else
353 curcol += n;
354 }
355 va_end(args);
356}
357
358void
359tprints(const char *str)
360{
361 if (outf) {
362 int n = fputs(str, outf);
363 if (n >= 0) {
364 curcol += strlen(str);
365 return;
366 }
367 if (outf != stderr)
368 perror(outfname == NULL
369 ? "<writing to pipe>" : outfname);
370 }
371}
372
373void
374printleader(struct tcb *tcp)
375{
376 if (printing_tcp) {
377 if (printing_tcp->ptrace_errno) {
378 if (printing_tcp->flags & TCB_INSYSCALL) {
379 tprints(" <unavailable>) ");
380 tabto();
381 }
382 tprints("= ? <unavailable>\n");
383 printing_tcp->ptrace_errno = 0;
384 } else if (!outfname || followfork < 2 || printing_tcp == tcp) {
385 printing_tcp->flags |= TCB_REPRINT;
386 tprints(" <unfinished ...>\n");
387 }
388 }
389
390 printing_tcp = tcp;
391 curcol = 0;
392
393 if (print_pid_pfx)
394 tprintf("%-5d ", tcp->pid);
395 else if (nprocs > 1 && !outfname)
396 tprintf("[pid %5u] ", tcp->pid);
397
398 if (tflag) {
399 char str[sizeof("HH:MM:SS")];
400 struct timeval tv, dtv;
401 static struct timeval otv;
402
403 gettimeofday(&tv, NULL);
404 if (rflag) {
405 if (otv.tv_sec == 0)
406 otv = tv;
407 tv_sub(&dtv, &tv, &otv);
408 tprintf("%6ld.%06ld ",
409 (long) dtv.tv_sec, (long) dtv.tv_usec);
410 otv = tv;
411 }
412 else if (tflag > 2) {
413 tprintf("%ld.%06ld ",
414 (long) tv.tv_sec, (long) tv.tv_usec);
415 }
416 else {
417 time_t local = tv.tv_sec;
418 strftime(str, sizeof(str), "%T", localtime(&local));
419 if (tflag > 1)
420 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
421 else
422 tprintf("%s ", str);
423 }
424 }
425 if (iflag)
426 printcall(tcp);
427}
428
429void
430tabto(void)
431{
432 if (curcol < acolumn)
433 tprints(acolumn_spaces + curcol);
434}
435
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000436/*
437 * When strace is setuid executable, we have to swap uids
438 * before and after filesystem and process management operations.
439 */
440static void
441swap_uid(void)
442{
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000443 int euid = geteuid(), uid = getuid();
444
Denys Vlasenko7b609d52011-06-22 14:32:43 +0200445 if (euid != uid && setreuid(euid, uid) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200446 perror_msg_and_die("setreuid");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000447 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000448}
449
Roland McGrath4bfa6262007-07-05 20:03:16 +0000450#if _LFS64_LARGEFILE
451# define fopen_for_output fopen64
452#else
453# define fopen_for_output fopen
454#endif
455
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000456static FILE *
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200457strace_fopen(const char *path)
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000458{
459 FILE *fp;
460
461 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200462 fp = fopen_for_output(path, "w");
463 if (!fp)
464 perror_msg_and_die("Can't fopen '%s'", path);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000465 swap_uid();
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200466 set_cloexec_flag(fileno(fp));
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000467 return fp;
468}
469
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200470static int popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000471
472#ifndef _PATH_BSHELL
473# define _PATH_BSHELL "/bin/sh"
474#endif
475
476/*
477 * We cannot use standard popen(3) here because we have to distinguish
478 * popen child process from other processes we trace, and standard popen(3)
479 * does not export its child's pid.
480 */
481static FILE *
482strace_popen(const char *command)
483{
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200484 FILE *fp;
485 int fds[2];
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000486
487 swap_uid();
488 if (pipe(fds) < 0)
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200489 perror_msg_and_die("pipe");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000490
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200491 set_cloexec_flag(fds[1]); /* never fails */
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000492
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200493 popen_pid = vfork();
494 if (popen_pid == -1)
495 perror_msg_and_die("vfork");
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000496
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200497 if (popen_pid == 0) {
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000498 /* child */
499 close(fds[1]);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200500 if (fds[0] != 0) {
501 if (dup2(fds[0], 0))
502 perror_msg_and_die("dup2");
503 close(fds[0]);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000504 }
505 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200506 perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000507 }
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200508
509 /* parent */
510 close(fds[0]);
511 swap_uid();
512 fp = fdopen(fds[1], "w");
513 if (!fp)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200514 die_out_of_memory();
Denys Vlasenko7dd23382011-06-22 13:03:56 +0200515 return fp;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000516}
517
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200518static void
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000519newoutf(struct tcb *tcp)
520{
521 if (outfname && followfork > 1) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000522 char name[520 + sizeof(int) * 3];
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000523 sprintf(name, "%.512s.%u", outfname, tcp->pid);
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200524 tcp->outf = strace_fopen(name);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000525 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +0000526}
527
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100528static void process_opt_p_list(char *opt)
529{
530 while (*opt) {
531 /*
532 * We accept -p PID,PID; -p "`pidof PROG`"; -p "`pgrep PROG`".
533 * pidof uses space as delim, pgrep uses newline. :(
534 */
535 int pid;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100536 char *delim = opt + strcspn(opt, ", \n\t");
537 char c = *delim;
538
539 *delim = '\0';
540 pid = atoi(opt); /* TODO: stricter parsing of the number? */
541 if (pid <= 0) {
542 error_msg("Invalid process id: '%s'", opt);
543 *delim = c;
544 return;
545 }
546 if (pid == strace_tracer_pid) {
547 error_msg("I'm sorry, I can't let you do that, Dave.");
548 *delim = c;
549 return;
550 }
551 *delim = c;
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100552 alloc_tcb(pid, 0);
Denys Vlasenkoe8172b72012-03-09 13:01:04 +0100553 if (c == '\0')
554 break;
555 opt = delim + 1;
556 }
557}
558
Roland McGrath02203312007-06-11 22:06:31 +0000559static void
560startup_attach(void)
561{
562 int tcbi;
563 struct tcb *tcp;
564
565 /*
566 * Block user interruptions as we would leave the traced
567 * process stopped (process state T) if we would terminate in
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200568 * between PTRACE_ATTACH and wait4() on SIGSTOP.
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200569 * We rely on cleanup() from this point on.
Roland McGrath02203312007-06-11 22:06:31 +0000570 */
571 if (interactive)
572 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
573
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000574 if (daemonized_tracer) {
575 pid_t pid = fork();
576 if (pid < 0) {
Denys Vlasenko014ca3a2011-09-02 16:19:30 +0200577 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000578 }
579 if (pid) { /* parent */
580 /*
Denys Vlasenko75422762011-05-27 14:36:01 +0200581 * Wait for grandchild to attach to straced process
582 * (grandparent). Grandchild SIGKILLs us after it attached.
583 * Grandparent's wait() is unblocked by our death,
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000584 * it proceeds to exec the straced program.
585 */
586 pause();
587 _exit(0); /* paranoia */
588 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200589 /* grandchild */
590 /* We will be the tracer process. Remember our new pid: */
591 strace_tracer_pid = getpid();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000592 }
593
Roland McGrath02203312007-06-11 22:06:31 +0000594 for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
595 tcp = tcbtab[tcbi];
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200596
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100597 if (!(tcp->flags & TCB_INUSE))
598 continue;
599
Denys Vlasenkod116a732011-09-05 14:01:33 +0200600 /* Is this a process we should attach to, but not yet attached? */
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100601 if (tcp->flags & TCB_ATTACHED)
602 continue; /* no, we already attached it */
Denys Vlasenkod116a732011-09-05 14:01:33 +0200603
604 /* Reinitialize the output since it may have changed */
Roland McGrath02203312007-06-11 22:06:31 +0000605 tcp->outf = outf;
Denys Vlasenko3d5ed412011-06-22 13:17:16 +0200606 newoutf(tcp);
Roland McGrath02203312007-06-11 22:06:31 +0000607
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000608 if (followfork && !daemonized_tracer) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000609 char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
Roland McGrath02203312007-06-11 22:06:31 +0000610 DIR *dir;
611
612 sprintf(procdir, "/proc/%d/task", tcp->pid);
613 dir = opendir(procdir);
614 if (dir != NULL) {
615 unsigned int ntid = 0, nerr = 0;
616 struct dirent *de;
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200617
Roland McGrath02203312007-06-11 22:06:31 +0000618 while ((de = readdir(dir)) != NULL) {
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200619 struct tcb *cur_tcp;
620 int tid;
621
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000622 if (de->d_fileno == 0)
Roland McGrath02203312007-06-11 22:06:31 +0000623 continue;
624 tid = atoi(de->d_name);
625 if (tid <= 0)
626 continue;
627 ++ntid;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100628 if (ptrace_attach_or_seize(tid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000629 ++nerr;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200630 if (debug)
631 fprintf(stderr, "attach to pid %d failed\n", tid);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200632 continue;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200633 }
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200634 if (debug)
635 fprintf(stderr, "attach to pid %d succeeded\n", tid);
636 cur_tcp = tcp;
637 if (tid != tcp->pid)
638 cur_tcp = alloctcb(tid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100639 cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrath02203312007-06-11 22:06:31 +0000640 }
641 closedir(dir);
Denys Vlasenko381dbc22011-09-05 13:59:39 +0200642 if (interactive) {
643 sigprocmask(SIG_SETMASK, &empty_set, NULL);
644 if (interrupted)
645 goto ret;
646 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
647 }
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000648 ntid -= nerr;
649 if (ntid == 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000650 perror("attach: ptrace(PTRACE_ATTACH, ...)");
651 droptcb(tcp);
652 continue;
653 }
654 if (!qflag) {
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000655 fprintf(stderr, ntid > 1
656? "Process %u attached with %u threads - interrupt to quit\n"
657: "Process %u attached - interrupt to quit\n",
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200658 tcp->pid, ntid);
Roland McGrath02203312007-06-11 22:06:31 +0000659 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100660 if (!(tcp->flags & TCB_ATTACHED)) {
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200661 /* -p PID, we failed to attach to PID itself
662 * but did attach to some of its sibling threads.
663 * Drop PID's tcp.
664 */
665 droptcb(tcp);
666 }
Roland McGrath02203312007-06-11 22:06:31 +0000667 continue;
Denys Vlasenko7a8bf062009-01-29 20:38:20 +0000668 } /* if (opendir worked) */
669 } /* if (-f) */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100670 if (ptrace_attach_or_seize(tcp->pid) < 0) {
Roland McGrath02203312007-06-11 22:06:31 +0000671 perror("attach: ptrace(PTRACE_ATTACH, ...)");
672 droptcb(tcp);
673 continue;
674 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100675 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200676 if (debug)
677 fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000678
679 if (daemonized_tracer) {
680 /*
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000681 * Make parent go away.
682 * Also makes grandparent's wait() unblock.
683 */
684 kill(getppid(), SIGKILL);
685 }
686
Roland McGrath02203312007-06-11 22:06:31 +0000687 if (!qflag)
688 fprintf(stderr,
689 "Process %u attached - interrupt to quit\n",
690 tcp->pid);
Denys Vlasenkof95397a2011-06-24 16:51:16 +0200691 } /* for each tcbtab[] */
Roland McGrath02203312007-06-11 22:06:31 +0000692
Denys Vlasenko44f87ef2011-08-17 15:18:21 +0200693 ret:
Roland McGrath02203312007-06-11 22:06:31 +0000694 if (interactive)
695 sigprocmask(SIG_SETMASK, &empty_set, NULL);
696}
697
698static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200699startup_child(char **argv)
Roland McGrath02203312007-06-11 22:06:31 +0000700{
701 struct stat statbuf;
702 const char *filename;
703 char pathname[MAXPATHLEN];
704 int pid = 0;
705 struct tcb *tcp;
706
707 filename = argv[0];
708 if (strchr(filename, '/')) {
709 if (strlen(filename) > sizeof pathname - 1) {
710 errno = ENAMETOOLONG;
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200711 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000712 }
713 strcpy(pathname, filename);
714 }
715#ifdef USE_DEBUGGING_EXEC
716 /*
717 * Debuggers customarily check the current directory
718 * first regardless of the path but doing that gives
719 * security geeks a panic attack.
720 */
721 else if (stat(filename, &statbuf) == 0)
722 strcpy(pathname, filename);
723#endif /* USE_DEBUGGING_EXEC */
724 else {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000725 const char *path;
Roland McGrath02203312007-06-11 22:06:31 +0000726 int m, n, len;
727
728 for (path = getenv("PATH"); path && *path; path += m) {
Denys Vlasenko4f3df072012-01-29 22:38:35 +0100729 const char *colon = strchr(path, ':');
730 if (colon) {
731 n = colon - path;
Roland McGrath02203312007-06-11 22:06:31 +0000732 m = n + 1;
733 }
734 else
735 m = n = strlen(path);
736 if (n == 0) {
737 if (!getcwd(pathname, MAXPATHLEN))
738 continue;
739 len = strlen(pathname);
740 }
741 else if (n > sizeof pathname - 1)
742 continue;
743 else {
744 strncpy(pathname, path, n);
745 len = n;
746 }
747 if (len && pathname[len - 1] != '/')
748 pathname[len++] = '/';
749 strcpy(pathname + len, filename);
750 if (stat(pathname, &statbuf) == 0 &&
751 /* Accept only regular files
752 with some execute bits set.
753 XXX not perfect, might still fail */
754 S_ISREG(statbuf.st_mode) &&
755 (statbuf.st_mode & 0111))
756 break;
757 }
758 }
759 if (stat(pathname, &statbuf) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200760 perror_msg_and_die("Can't stat '%s'", filename);
Roland McGrath02203312007-06-11 22:06:31 +0000761 }
Dmitry V. Levina6809652008-11-10 17:14:58 +0000762 strace_child = pid = fork();
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000763 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200764 perror_msg_and_die("fork");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000765 }
Denys Vlasenko75422762011-05-27 14:36:01 +0200766 if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
767 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000768 ) {
769 pid = getpid();
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200770 if (outf != stderr)
771 close(fileno(outf));
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100772 if (!daemonized_tracer && !use_seize) {
773 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200774 perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000775 }
Roland McGrath02203312007-06-11 22:06:31 +0000776 }
Roland McGrath02203312007-06-11 22:06:31 +0000777
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200778 if (username != NULL) {
Roland McGrath02203312007-06-11 22:06:31 +0000779 uid_t run_euid = run_uid;
780 gid_t run_egid = run_gid;
781
782 if (statbuf.st_mode & S_ISUID)
783 run_euid = statbuf.st_uid;
784 if (statbuf.st_mode & S_ISGID)
785 run_egid = statbuf.st_gid;
Roland McGrath02203312007-06-11 22:06:31 +0000786 /*
787 * It is important to set groups before we
788 * lose privileges on setuid.
789 */
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200790 if (initgroups(username, run_gid) < 0) {
791 perror_msg_and_die("initgroups");
792 }
793 if (setregid(run_gid, run_egid) < 0) {
794 perror_msg_and_die("setregid");
795 }
796 if (setreuid(run_uid, run_euid) < 0) {
797 perror_msg_and_die("setreuid");
Roland McGrath02203312007-06-11 22:06:31 +0000798 }
799 }
Denys Vlasenkoab034fb2011-09-01 10:27:42 +0200800 else if (geteuid() != 0)
Roland McGrath02203312007-06-11 22:06:31 +0000801 setreuid(run_uid, run_uid);
802
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000803 if (!daemonized_tracer) {
804 /*
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200805 * Induce a ptrace stop. Tracer (our parent)
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000806 * will resume us with PTRACE_SYSCALL and display
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200807 * the immediately following execve syscall.
808 * Can't do this on NOMMU systems, we are after
809 * vfork: parent is blocked, stopping would deadlock.
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000810 */
Mike Frysingerc1a5b7e2009-10-07 20:41:29 -0400811 if (!strace_vforked)
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200812 kill(pid, SIGSTOP);
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000813 } else {
814 struct sigaction sv_sigchld;
815 sigaction(SIGCHLD, NULL, &sv_sigchld);
816 /*
817 * Make sure it is not SIG_IGN, otherwise wait
818 * will not block.
819 */
820 signal(SIGCHLD, SIG_DFL);
821 /*
822 * Wait for grandchild to attach to us.
823 * It kills child after that, and wait() unblocks.
824 */
825 alarm(3);
826 wait(NULL);
827 alarm(0);
828 sigaction(SIGCHLD, &sv_sigchld, NULL);
829 }
Roland McGrath02203312007-06-11 22:06:31 +0000830
831 execv(pathname, argv);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +0200832 perror_msg_and_die("exec");
Roland McGrath02203312007-06-11 22:06:31 +0000833 }
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000834
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200835 /* We are the tracer */
Denys Vlasenko75422762011-05-27 14:36:01 +0200836
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200837 if (!daemonized_tracer) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100838 if (!use_seize) {
839 /* child did PTRACE_TRACEME, nothing to do in parent */
840 } else {
841 if (!strace_vforked) {
842 /* Wait until child stopped itself */
843 int status;
844 while (waitpid(pid, &status, WSTOPPED) < 0) {
845 if (errno == EINTR)
846 continue;
847 perror_msg_and_die("waitpid");
848 }
849 if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100850 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100851 perror_msg_and_die("Unexpected wait status %x", status);
852 }
853 }
854 /* Else: vforked case, we have no way to sync.
855 * Just attach to it as soon as possible.
856 * This means that we may miss a few first syscalls...
857 */
858
859 if (ptrace_attach_or_seize(pid)) {
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100860 kill_save_errno(pid, SIGKILL);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100861 perror_msg_and_die("Can't attach to %d", pid);
862 }
863 if (!strace_vforked)
864 kill(pid, SIGCONT);
865 }
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200866 tcp = alloctcb(pid);
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200867 if (!strace_vforked)
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100868 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP | post_attach_sigstop;
Denys Vlasenkof88837a2011-09-05 14:05:46 +0200869 else
Denys Vlasenko75fe85c2012-03-09 15:15:24 +0100870 tcp->flags |= TCB_ATTACHED | TCB_STRACE_CHILD | TCB_STARTUP;
Denys Vlasenko2e968c02011-09-01 10:23:09 +0200871 }
872 else {
873 /* With -D, *we* are child here, IOW: different pid. Fetch it: */
874 strace_tracer_pid = getpid();
875 /* The tracee is our parent: */
876 pid = getppid();
Denys Vlasenkof2025022012-03-09 15:29:45 +0100877 alloctcb(pid);
878 /* attaching will be done later, by startup_attach */
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +0000879 }
Roland McGrath02203312007-06-11 22:06:31 +0000880}
881
Wang Chaob13c0de2010-11-12 17:25:19 +0800882/*
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000883 * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
Wang Chaob13c0de2010-11-12 17:25:19 +0800884 * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000885 * and then see which options are supported by the kernel.
Wang Chaob13c0de2010-11-12 17:25:19 +0800886 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000887static void
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200888test_ptrace_setoptions_followfork(void)
Wang Chaob13c0de2010-11-12 17:25:19 +0800889{
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000890 int pid, expected_grandchild = 0, found_grandchild = 0;
891 const unsigned int test_options = PTRACE_O_TRACECLONE |
892 PTRACE_O_TRACEFORK |
893 PTRACE_O_TRACEVFORK;
Wang Chaob13c0de2010-11-12 17:25:19 +0800894
Denys Vlasenko5d645812011-08-20 12:48:18 +0200895 pid = fork();
896 if (pid < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000897 perror_msg_and_die("fork");
Denys Vlasenko5d645812011-08-20 12:48:18 +0200898 if (pid == 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000899 pid = getpid();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +0100900 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000901 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
902 __func__);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100903 kill_save_errno(pid, SIGSTOP);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000904 if (fork() < 0)
905 perror_msg_and_die("fork");
906 _exit(0);
Wang Chaob13c0de2010-11-12 17:25:19 +0800907 }
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000908
909 while (1) {
910 int status, tracee_pid;
911
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000912 errno = 0;
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000913 tracee_pid = wait(&status);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000914 if (tracee_pid <= 0) {
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000915 if (errno == EINTR)
916 continue;
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100917 if (errno == ECHILD)
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000918 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000919 kill_save_errno(pid, SIGKILL);
920 perror_msg_and_die("%s: unexpected wait result %d",
921 __func__, tracee_pid);
922 }
923 if (WIFEXITED(status)) {
924 if (WEXITSTATUS(status)) {
925 if (tracee_pid != pid)
926 kill_save_errno(pid, SIGKILL);
927 error_msg_and_die("%s: unexpected exit status %u",
928 __func__, WEXITSTATUS(status));
929 }
930 continue;
931 }
932 if (WIFSIGNALED(status)) {
933 if (tracee_pid != pid)
934 kill_save_errno(pid, SIGKILL);
935 error_msg_and_die("%s: unexpected signal %u",
936 __func__, WTERMSIG(status));
937 }
938 if (!WIFSTOPPED(status)) {
939 if (tracee_pid != pid)
940 kill_save_errno(tracee_pid, SIGKILL);
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100941 kill_save_errno(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000942 error_msg_and_die("%s: unexpected wait status %x",
943 __func__, status);
Dmitry V. Levinb1467442010-12-02 20:56:43 +0000944 }
945 if (tracee_pid != pid) {
Dmitry V. Levin2fabd0e2011-02-19 21:33:50 +0000946 found_grandchild = tracee_pid;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000947 if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
948 kill_save_errno(tracee_pid, SIGKILL);
949 kill_save_errno(pid, SIGKILL);
950 perror_msg_and_die("PTRACE_CONT doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800951 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000952 continue;
953 }
954 switch (WSTOPSIG(status)) {
955 case SIGSTOP:
956 if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
957 && errno != EINVAL && errno != EIO)
958 perror_msg("PTRACE_SETOPTIONS");
959 break;
960 case SIGTRAP:
961 if (status >> 16 == PTRACE_EVENT_FORK) {
962 long msg = 0;
963
964 if (ptrace(PTRACE_GETEVENTMSG, pid,
965 NULL, (long) &msg) == 0)
966 expected_grandchild = msg;
967 }
968 break;
969 }
970 if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
971 kill_save_errno(pid, SIGKILL);
972 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Wang Chaob13c0de2010-11-12 17:25:19 +0800973 }
974 }
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000975 if (expected_grandchild && expected_grandchild == found_grandchild) {
Denys Vlasenkof44cce42011-06-21 14:34:10 +0200976 ptrace_setoptions |= test_options;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +0000977 if (debug)
978 fprintf(stderr, "ptrace_setoptions = %#x\n",
979 ptrace_setoptions);
980 return;
981 }
982 error_msg("Test for PTRACE_O_TRACECLONE failed, "
983 "giving up using this feature.");
Wang Chaob13c0de2010-11-12 17:25:19 +0800984}
Denys Vlasenko3454e4b2011-05-23 21:29:03 +0200985
986/*
987 * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
988 * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
989 * and then see whether it will stop with (SIGTRAP | 0x80).
990 *
991 * Use of this option enables correct handling of user-generated SIGTRAPs,
992 * and SIGTRAPs generated by special instructions such as int3 on x86:
993 * _start: .globl _start
994 * int3
995 * movl $42, %ebx
996 * movl $1, %eax
997 * int $0x80
998 * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
999 */
1000static void
1001test_ptrace_setoptions_for_all(void)
1002{
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001003 const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
1004 PTRACE_O_TRACEEXEC;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001005 int pid;
1006 int it_worked = 0;
1007
1008 pid = fork();
1009 if (pid < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001010 perror_msg_and_die("fork");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001011
1012 if (pid == 0) {
1013 pid = getpid();
1014 if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
Denys Vlasenko75422762011-05-27 14:36:01 +02001015 /* Note: exits with exitcode 1 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001016 perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
1017 __func__);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001018 kill(pid, SIGSTOP);
1019 _exit(0); /* parent should see entry into this syscall */
1020 }
1021
1022 while (1) {
1023 int status, tracee_pid;
1024
1025 errno = 0;
1026 tracee_pid = wait(&status);
1027 if (tracee_pid <= 0) {
1028 if (errno == EINTR)
1029 continue;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001030 kill_save_errno(pid, SIGKILL);
1031 perror_msg_and_die("%s: unexpected wait result %d",
1032 __func__, tracee_pid);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001033 }
Denys Vlasenko75422762011-05-27 14:36:01 +02001034 if (WIFEXITED(status)) {
1035 if (WEXITSTATUS(status) == 0)
1036 break;
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001037 error_msg_and_die("%s: unexpected exit status %u",
1038 __func__, WEXITSTATUS(status));
1039 }
1040 if (WIFSIGNALED(status)) {
1041 error_msg_and_die("%s: unexpected signal %u",
1042 __func__, WTERMSIG(status));
Denys Vlasenko75422762011-05-27 14:36:01 +02001043 }
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001044 if (!WIFSTOPPED(status)) {
1045 kill(pid, SIGKILL);
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001046 error_msg_and_die("%s: unexpected wait status %x",
1047 __func__, status);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001048 }
1049 if (WSTOPSIG(status) == SIGSTOP) {
1050 /*
1051 * We don't check "options aren't accepted" error.
1052 * If it happens, we'll never get (SIGTRAP | 0x80),
1053 * and thus will decide to not use the option.
1054 * IOW: the outcome of the test will be correct.
1055 */
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001056 if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
1057 && errno != EINVAL && errno != EIO)
1058 perror_msg("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001059 }
1060 if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
1061 it_worked = 1;
1062 }
1063 if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001064 kill_save_errno(pid, SIGKILL);
Denys Vlasenko75422762011-05-27 14:36:01 +02001065 perror_msg_and_die("PTRACE_SYSCALL doesn't work");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001066 }
1067 }
1068
1069 if (it_worked) {
Denys Vlasenko75422762011-05-27 14:36:01 +02001070 syscall_trap_sig = (SIGTRAP | 0x80);
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001071 ptrace_setoptions |= test_options;
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001072 if (debug)
Denys Vlasenkof44cce42011-06-21 14:34:10 +02001073 fprintf(stderr, "ptrace_setoptions = %#x\n",
1074 ptrace_setoptions);
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001075 return;
1076 }
1077
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001078 error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
1079 "giving up using this feature.");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001080}
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001081
1082# ifdef USE_SEIZE
1083static void
1084test_ptrace_seize(void)
1085{
1086 int pid;
1087
1088 pid = fork();
1089 if (pid < 0)
1090 perror_msg_and_die("fork");
1091
1092 if (pid == 0) {
1093 pause();
1094 _exit(0);
1095 }
1096
1097 /* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap. After
1098 * attaching tracee continues to run unless a trap condition occurs.
1099 * PTRACE_SEIZE doesn't affect signal or group stop state.
1100 */
1101 if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
1102 post_attach_sigstop = 0; /* this sets use_seize to 1 */
1103 } else if (debug) {
1104 fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
1105 }
1106
1107 kill(pid, SIGKILL);
1108
1109 while (1) {
1110 int status, tracee_pid;
1111
1112 errno = 0;
1113 tracee_pid = waitpid(pid, &status, 0);
1114 if (tracee_pid <= 0) {
1115 if (errno == EINTR)
1116 continue;
1117 perror_msg_and_die("%s: unexpected wait result %d",
1118 __func__, tracee_pid);
1119 }
1120 if (WIFSIGNALED(status)) {
1121 return;
1122 }
1123 error_msg_and_die("%s: unexpected wait status %x",
1124 __func__, status);
1125 }
1126}
1127# else /* !USE_SEIZE */
1128# define test_ptrace_seize() ((void)0)
1129# endif
1130
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001131static void
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001132get_os_release(void)
1133{
1134 struct utsname u;
1135 if (uname(&u) < 0)
1136 perror_msg_and_die("uname");
1137 os_release = strdup(u.release);
1138 if (!os_release)
1139 die_out_of_memory();
1140}
1141
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01001142/*
1143 * Initialization part of main() was eating much stack (~0.5k),
1144 * which was unused after init.
1145 * We can reuse it if we move init code into a separate function.
1146 *
1147 * Don't want main() to inline us and defeat the reason
1148 * we have a separate function.
1149 */
1150static void __attribute__ ((noinline))
1151init(int argc, char *argv[])
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 struct tcb *tcp;
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001154 int c;
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001155 int optF = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 struct sigaction sa;
1157
Dmitry V. Levin08b623e2007-10-08 21:04:41 +00001158 progname = argv[0] ? argv[0] : "strace";
1159
Denys Vlasenko75422762011-05-27 14:36:01 +02001160 strace_tracer_pid = getpid();
1161
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001162 get_os_release();
1163
Roland McGrathee9d4352002-12-18 04:16:10 +00001164 /* Allocate the initial tcbtab. */
1165 tcbtabsize = argc; /* Surely enough for all -p args. */
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001166 tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001167 if (!tcbtab)
1168 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001169 tcp = calloc(tcbtabsize, sizeof(*tcp));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001170 if (!tcp)
1171 die_out_of_memory();
Denys Vlasenko4f12af22011-06-23 13:16:23 +02001172 for (c = 0; c < tcbtabsize; c++)
1173 tcbtab[c] = tcp++;
Roland McGrathee9d4352002-12-18 04:16:10 +00001174
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 outf = stderr;
Roland McGrath138c6a32006-01-12 09:50:49 +00001176 set_sortby(DEFAULT_SORTBY);
1177 set_personality(DEFAULT_PERSONALITY);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 qualify("trace=all");
1179 qualify("abbrev=all");
1180 qualify("verbose=all");
1181 qualify("signal=all");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 while ((c = getopt(argc, argv,
Grant Edwards8a082772011-04-07 20:25:40 +00001183 "+cCdfFhiqrtTvVxyz"
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001184 "D"
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001185 "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 switch (c) {
1187 case 'c':
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001188 if (cflag == CFLAG_BOTH) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001189 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001190 }
1191 cflag = CFLAG_ONLY_STATS;
1192 break;
1193 case 'C':
1194 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001195 error_msg_and_die("-c and -C are mutually exclusive options");
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001196 }
1197 cflag = CFLAG_BOTH;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198 break;
1199 case 'd':
1200 debug++;
1201 break;
Denys Vlasenkoecfe2f12008-12-30 20:51:30 +00001202 case 'D':
1203 daemonized_tracer = 1;
1204 break;
Roland McGrath41c48222008-07-18 00:25:10 +00001205 case 'F':
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001206 optF = 1;
1207 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 case 'f':
1209 followfork++;
1210 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 case 'h':
1212 usage(stdout, 0);
1213 break;
1214 case 'i':
1215 iflag++;
1216 break;
1217 case 'q':
1218 qflag++;
1219 break;
1220 case 'r':
1221 rflag++;
1222 tflag++;
1223 break;
1224 case 't':
1225 tflag++;
1226 break;
1227 case 'T':
1228 dtime++;
1229 break;
1230 case 'x':
1231 xflag++;
1232 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001233 case 'y':
1234 show_fd_path = 1;
1235 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236 case 'v':
1237 qualify("abbrev=none");
1238 break;
1239 case 'V':
Roland McGrath9c9a2532003-02-20 02:56:29 +00001240 printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001241 exit(0);
1242 break;
Michal Ludvig17f8fb32002-11-06 13:17:21 +00001243 case 'z':
1244 not_failing_only = 1;
1245 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001246 case 'a':
1247 acolumn = atoi(optarg);
Denys Vlasenko102ec492011-08-25 01:27:59 +02001248 if (acolumn < 0)
1249 error_msg_and_die("Bad column width '%s'", optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250 break;
1251 case 'e':
1252 qualify(optarg);
1253 break;
1254 case 'o':
1255 outfname = strdup(optarg);
1256 break;
1257 case 'O':
1258 set_overhead(atoi(optarg));
1259 break;
1260 case 'p':
Denys Vlasenkoe8172b72012-03-09 13:01:04 +01001261 process_opt_p_list(optarg);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001262 break;
Grant Edwards8a082772011-04-07 20:25:40 +00001263 case 'P':
1264 tracing_paths = 1;
1265 if (pathtrace_select(optarg)) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001266 error_msg_and_die("Failed to select path '%s'", optarg);
Grant Edwards8a082772011-04-07 20:25:40 +00001267 }
1268 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001269 case 's':
1270 max_strlen = atoi(optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001271 if (max_strlen < 0) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001272 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
Roland McGrathdccec722005-05-09 07:45:47 +00001273 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 break;
1275 case 'S':
1276 set_sortby(optarg);
1277 break;
1278 case 'u':
1279 username = strdup(optarg);
1280 break;
Roland McGrathde6e5332003-01-24 04:31:23 +00001281 case 'E':
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001282 if (putenv(optarg) < 0)
1283 die_out_of_memory();
Roland McGrathde6e5332003-01-24 04:31:23 +00001284 break;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001285 case 'I':
1286 opt_intr = atoi(optarg);
1287 if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1288 error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1289 }
1290 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001291 default:
1292 usage(stderr, 1);
1293 break;
1294 }
1295 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001296 argv += optind;
1297 /* argc -= optind; - no need, argc is not used below */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298
Denys Vlasenko102ec492011-08-25 01:27:59 +02001299 acolumn_spaces = malloc(acolumn + 1);
1300 if (!acolumn_spaces)
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001301 die_out_of_memory();
Denys Vlasenko102ec492011-08-25 01:27:59 +02001302 memset(acolumn_spaces, ' ', acolumn);
1303 acolumn_spaces[acolumn] = '\0';
1304
Denys Vlasenko837399a2012-01-24 11:37:03 +01001305 /* Must have PROG [ARGS], or -p PID. Not both. */
Denys Vlasenkofd883382012-03-09 13:03:41 +01001306 if (!argv[0] == !nprocs)
Roland McGrathce0d1542003-11-11 21:24:23 +00001307 usage(stderr, 1);
1308
Denys Vlasenkofd883382012-03-09 13:03:41 +01001309 if (nprocs != 0 && daemonized_tracer) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001310 error_msg_and_die("-D and -p are mutually exclusive options");
Wang Chaod322a4b2010-08-05 14:30:11 +08001311 }
1312
Dmitry V. Levin06350db2008-07-25 15:42:34 +00001313 if (!followfork)
1314 followfork = optF;
1315
Roland McGrathcb9def62006-04-25 07:48:03 +00001316 if (followfork > 1 && cflag) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001317 error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
Roland McGrathcb9def62006-04-25 07:48:03 +00001318 }
1319
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 /* See if they want to run as another user. */
1321 if (username != NULL) {
1322 struct passwd *pent;
1323
1324 if (getuid() != 0 || geteuid() != 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001325 error_msg_and_die("You must be root to use the -u option");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 }
Denys Vlasenko5d645812011-08-20 12:48:18 +02001327 pent = getpwnam(username);
1328 if (pent == NULL) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001329 error_msg_and_die("Cannot find user '%s'", username);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 }
1331 run_uid = pent->pw_uid;
1332 run_gid = pent->pw_gid;
1333 }
1334 else {
1335 run_uid = getuid();
1336 run_gid = getgid();
1337 }
1338
Dmitry V. Levin04f8b482011-08-16 18:57:29 +00001339 if (followfork)
1340 test_ptrace_setoptions_followfork();
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001341 test_ptrace_setoptions_for_all();
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001342 test_ptrace_seize();
Dmitry V. Levin8044bc12010-12-07 12:50:49 +00001343
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344 /* Check if they want to redirect the output. */
1345 if (outfname) {
Roland McGrath37b9a662003-11-07 02:26:54 +00001346 /* See if they want to pipe the output. */
1347 if (outfname[0] == '|' || outfname[0] == '!') {
1348 /*
1349 * We can't do the <outfname>.PID funny business
1350 * when using popen, so prohibit it.
1351 */
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001352 if (followfork > 1)
1353 error_msg_and_die("Piping the output and -ff are mutually exclusive");
1354 outf = strace_popen(outfname + 1);
Roland McGrath37b9a662003-11-07 02:26:54 +00001355 }
Denys Vlasenko3d5ed412011-06-22 13:17:16 +02001356 else if (followfork <= 1)
1357 outf = strace_fopen(outfname);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358 }
1359
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001360 if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
Denys Vlasenkoa677da52012-01-24 11:31:51 +01001361 char *buf = malloc(BUFSIZ);
1362 if (!buf)
1363 die_out_of_memory();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364 setvbuf(outf, buf, _IOLBF, BUFSIZ);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001365 }
Denys Vlasenko837399a2012-01-24 11:37:03 +01001366 if (outfname && argv[0]) {
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001367 if (!opt_intr)
1368 opt_intr = INTR_NEVER;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369 qflag = 1;
Roland McGrath36931052003-06-03 01:35:20 +00001370 }
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001371 if (!opt_intr)
1372 opt_intr = INTR_WHILE_WAIT;
Wang Chaob13c0de2010-11-12 17:25:19 +08001373
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001374 /* argv[0] -pPID -oFILE Default interactive setting
1375 * yes 0 0 INTR_WHILE_WAIT
1376 * no 1 0 INTR_WHILE_WAIT
1377 * yes 0 1 INTR_NEVER
1378 * no 1 1 INTR_WHILE_WAIT
Roland McGrath54cc1c82007-11-03 23:34:11 +00001379 */
1380
1381 /* STARTUP_CHILD must be called before the signal handlers get
1382 installed below as they are inherited into the spawned process.
1383 Also we do not need to be protected by them as during interruption
1384 in the STARTUP_CHILD mode we kill the spawned process anyway. */
Denys Vlasenko837399a2012-01-24 11:37:03 +01001385 if (argv[0])
1386 startup_child(argv);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001387
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388 sigemptyset(&empty_set);
1389 sigemptyset(&blocked_set);
1390 sa.sa_handler = SIG_IGN;
1391 sigemptyset(&sa.sa_mask);
1392 sa.sa_flags = 0;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001393 sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1394 sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1395 if (opt_intr != INTR_ANYWHERE) {
1396 if (opt_intr == INTR_BLOCK_TSTP_TOO)
1397 sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1398 /*
1399 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1400 * fatal signals are blocked while syscall stop is processed,
1401 * and acted on in between, when waiting for new syscall stops.
1402 * In non-interactive mode, signals are ignored.
1403 */
1404 if (opt_intr == INTR_WHILE_WAIT) {
1405 sigaddset(&blocked_set, SIGHUP);
1406 sigaddset(&blocked_set, SIGINT);
1407 sigaddset(&blocked_set, SIGQUIT);
1408 sigaddset(&blocked_set, SIGPIPE);
1409 sigaddset(&blocked_set, SIGTERM);
1410 sa.sa_handler = interrupt;
Denys Vlasenkob51581e2012-01-29 16:53:03 +01001411 }
1412 /* SIG_IGN, or set handler for these */
1413 sigaction(SIGHUP, &sa, NULL);
1414 sigaction(SIGINT, &sa, NULL);
1415 sigaction(SIGQUIT, &sa, NULL);
1416 sigaction(SIGPIPE, &sa, NULL);
1417 sigaction(SIGTERM, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418 }
Roland McGrath553a6092002-12-16 20:40:39 +00001419 /* Make sure SIGCHLD has the default action so that waitpid
1420 definitely works without losing track of children. The user
1421 should not have given us a bogus state to inherit, but he might
1422 have. Arguably we should detect SIG_IGN here and pass it on
1423 to children, but probably noone really needs that. */
1424 sa.sa_handler = SIG_DFL;
1425 sigaction(SIGCHLD, &sa, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001426
Denys Vlasenkofd883382012-03-09 13:03:41 +01001427 if (nprocs != 0 || daemonized_tracer)
Roland McGrath02203312007-06-11 22:06:31 +00001428 startup_attach();
Roland McGrath02203312007-06-11 22:06:31 +00001429
Denys Vlasenkofd883382012-03-09 13:03:41 +01001430 /* Do we want pids printed in our -o OUTFILE?
1431 * -ff: no (every pid has its own file); or
1432 * -f: yes (there can be more pids in the future); or
1433 * -p PID1,PID2: yes (there are already more than one pid)
1434 */
1435 print_pid_pfx = (outfname && followfork < 2 && (followfork == 1 || nprocs > 1));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436}
1437
Denys Vlasenko2b60c352011-06-22 12:45:25 +02001438static void
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001439expand_tcbtab(void)
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001440{
1441 /* Allocate some more TCBs and expand the table.
1442 We don't want to relocate the TCBs because our
1443 callers have pointers and it would be a pain.
1444 So tcbtab is a table of pointers. Since we never
1445 free the TCBs, we allocate a single chunk of many. */
Denys Vlasenko18da2732011-06-22 12:41:57 +02001446 int i = tcbtabsize;
1447 struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
1448 struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
Denys Vlasenko1d46ba52011-08-31 14:00:02 +02001449 if (!newtab || !newtcbs)
1450 die_out_of_memory();
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001451 tcbtabsize *= 2;
1452 tcbtab = newtab;
Denys Vlasenko18da2732011-06-22 12:41:57 +02001453 while (i < tcbtabsize)
1454 tcbtab[i++] = newtcbs++;
Roland McGrath7b54a7a2004-06-04 01:50:45 +00001455}
1456
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001457struct tcb *
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001458alloc_tcb(int pid, int command_options_parsed)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001459{
1460 int i;
1461 struct tcb *tcp;
1462
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001463 if (nprocs == tcbtabsize)
1464 expand_tcbtab();
1465
Roland McGrathee9d4352002-12-18 04:16:10 +00001466 for (i = 0; i < tcbtabsize; i++) {
1467 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001468 if ((tcp->flags & TCB_INUSE) == 0) {
Denys Vlasenko18da2732011-06-22 12:41:57 +02001469 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470 tcp->pid = pid;
Denys Vlasenko381dbc22011-09-05 13:59:39 +02001471 tcp->flags = TCB_INUSE;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472 tcp->outf = outf; /* Initialise to current out file */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001473#if SUPPORTED_PERSONALITIES > 1
1474 tcp->currpers = current_personality;
1475#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476 nprocs++;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001477 if (debug)
1478 fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001479 if (command_options_parsed)
1480 newoutf(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481 return tcp;
1482 }
1483 }
Denys Vlasenko18da2732011-06-22 12:41:57 +02001484 error_msg_and_die("bug in alloc_tcb");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485}
1486
Denys Vlasenkoeebb04d2012-01-27 15:24:48 +01001487static struct tcb *
Roland McGrath54e931f2010-09-14 18:59:20 -07001488pid2tcb(int pid)
1489{
1490 int i;
1491
1492 if (pid <= 0)
1493 return NULL;
1494
1495 for (i = 0; i < tcbtabsize; i++) {
1496 struct tcb *tcp = tcbtab[i];
1497 if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
1498 return tcp;
1499 }
1500
1501 return NULL;
1502}
1503
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504void
Denys Vlasenko12014262011-05-30 14:00:14 +02001505droptcb(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001506{
1507 if (tcp->pid == 0)
1508 return;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001509
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510 nprocs--;
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001511 if (debug)
1512 fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001513
Wichert Akkerman822f0c92002-04-03 10:55:14 +00001514 if (outfname && followfork > 1 && tcp->outf)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001515 fclose(tcp->outf);
Wichert Akkermaneb8ebda2002-04-01 17:48:02 +00001516
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001517 memset(tcp, 0, sizeof(*tcp));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518}
1519
Roland McGrath0a463882007-07-05 18:43:16 +00001520/* detach traced process; continue with sig
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001521 * Never call DETACH twice on the same process as both unattached and
1522 * attached-unstopped processes give the same ESRCH. For unattached process we
1523 * would SIGSTOP it and wait for its SIGSTOP notification forever.
1524 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525static int
Denys Vlasenko4c196382012-01-04 15:11:09 +01001526detach(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527{
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001528 int error;
1529 int status, sigstop_expected;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530
1531 if (tcp->flags & TCB_BPTSET)
Andreas Schwab840d85b2010-01-12 11:16:32 +01001532 clearbpt(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534 /*
1535 * Linux wrongly insists the child be stopped
Roland McGrath7bf10472002-12-16 20:42:50 +00001536 * before detaching. Arghh. We go through hoops
1537 * to make a clean break of things.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538 */
Roland McGrath7bf10472002-12-16 20:42:50 +00001539#if defined(SPARC)
1540#undef PTRACE_DETACH
1541#define PTRACE_DETACH PTRACE_SUNDETACH
1542#endif
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001543
1544 sigstop_expected = 0;
1545 if (tcp->flags & TCB_ATTACHED) {
1546 /*
1547 * We attached but possibly didn't see the expected SIGSTOP.
1548 * We must catch exactly one as otherwise the detached process
1549 * would be left stopped (process state T).
1550 */
1551 sigstop_expected = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
1552 error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
1553 if (error == 0) {
1554 /* On a clear day, you can see forever. */
1555 }
1556 else if (errno != ESRCH) {
1557 /* Shouldn't happen. */
1558 perror("detach: ptrace(PTRACE_DETACH, ...)");
1559 }
1560 else if (my_tkill(tcp->pid, 0) < 0) {
1561 if (errno != ESRCH)
1562 perror("detach: checking sanity");
1563 }
1564 else if (!sigstop_expected && my_tkill(tcp->pid, SIGSTOP) < 0) {
1565 if (errno != ESRCH)
1566 perror("detach: stopping child");
1567 }
1568 else
1569 sigstop_expected = 1;
Roland McGrath7bf10472002-12-16 20:42:50 +00001570 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001571
1572 if (sigstop_expected) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001573 for (;;) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001574#ifdef __WALL
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001575 if (waitpid(tcp->pid, &status, __WALL) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001576 if (errno == ECHILD) /* Already gone. */
1577 break;
1578 if (errno != EINVAL) {
Roland McGrath553a6092002-12-16 20:40:39 +00001579 perror("detach: waiting");
Roland McGrath7508cb42002-12-17 10:48:05 +00001580 break;
1581 }
1582#endif /* __WALL */
1583 /* No __WALL here. */
1584 if (waitpid(tcp->pid, &status, 0) < 0) {
1585 if (errno != ECHILD) {
1586 perror("detach: waiting");
1587 break;
1588 }
1589#ifdef __WCLONE
1590 /* If no processes, try clones. */
Denys Vlasenko37ab4b72012-03-09 15:34:16 +01001591 if (waitpid(tcp->pid, &status, __WCLONE) < 0) {
Roland McGrath7508cb42002-12-17 10:48:05 +00001592 if (errno != ECHILD)
1593 perror("detach: waiting");
1594 break;
1595 }
1596#endif /* __WCLONE */
1597 }
1598#ifdef __WALL
Roland McGrath553a6092002-12-16 20:40:39 +00001599 }
Roland McGrath7508cb42002-12-17 10:48:05 +00001600#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601 if (!WIFSTOPPED(status)) {
1602 /* Au revoir, mon ami. */
1603 break;
1604 }
1605 if (WSTOPSIG(status) == SIGSTOP) {
Denys Vlasenko4c196382012-01-04 15:11:09 +01001606 ptrace_restart(PTRACE_DETACH, tcp, 0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607 break;
1608 }
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001609 error = ptrace_restart(PTRACE_CONT, tcp,
Denys Vlasenko75422762011-05-27 14:36:01 +02001610 WSTOPSIG(status) == syscall_trap_sig ? 0
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001611 : WSTOPSIG(status));
1612 if (error < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001613 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 }
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00001615 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001617 if (!qflag && (tcp->flags & TCB_ATTACHED))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 fprintf(stderr, "Process %u detached\n", tcp->pid);
1619
1620 droptcb(tcp);
Roland McGratha08a97e2005-08-03 11:23:46 +00001621
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 return error;
1623}
1624
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001626cleanup(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627{
1628 int i;
1629 struct tcb *tcp;
Denys Vlasenko35218842012-01-29 21:17:56 +01001630 int fatal_sig;
1631
1632 /* 'interrupted' is a volatile object, fetch it only once */
1633 fatal_sig = interrupted;
1634 if (!fatal_sig)
1635 fatal_sig = SIGTERM;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636
Roland McGrathee9d4352002-12-18 04:16:10 +00001637 for (i = 0; i < tcbtabsize; i++) {
1638 tcp = tcbtab[i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001639 if (!(tcp->flags & TCB_INUSE))
1640 continue;
1641 if (debug)
1642 fprintf(stderr,
1643 "cleanup: looking at pid %u\n", tcp->pid);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001644 if (printing_tcp &&
1645 (!outfname || followfork < 2 || printing_tcp == tcp)) {
1646 tprints(" <unfinished ...>\n");
1647 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 }
Denys Vlasenko75fe85c2012-03-09 15:15:24 +01001649 if (!(tcp->flags & TCB_STRACE_CHILD))
Denys Vlasenko4c196382012-01-04 15:11:09 +01001650 detach(tcp);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651 else {
1652 kill(tcp->pid, SIGCONT);
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001653 kill(tcp->pid, fatal_sig);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654 }
1655 }
1656 if (cflag)
1657 call_summary(outf);
1658}
1659
1660static void
Denys Vlasenko12014262011-05-30 14:00:14 +02001661interrupt(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001662{
Denys Vlasenkoa3559252012-01-29 16:43:51 +01001663 interrupted = sig;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664}
1665
1666#ifndef HAVE_STRERROR
1667
Roland McGrath6d2b3492002-12-30 00:51:30 +00001668#if !HAVE_DECL_SYS_ERRLIST
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669extern int sys_nerr;
1670extern char *sys_errlist[];
Roland McGrath6d2b3492002-12-30 00:51:30 +00001671#endif /* HAVE_DECL_SYS_ERRLIST */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672
1673const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001674strerror(int err_no)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001676 static char buf[sizeof("Unknown error %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001678 if (err_no < 1 || err_no >= sys_nerr) {
1679 sprintf(buf, "Unknown error %d", err_no);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 return buf;
1681 }
Denys Vlasenko35aba6a2011-05-25 15:33:26 +02001682 return sys_errlist[err_no];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683}
1684
1685#endif /* HAVE_STERRROR */
1686
1687#ifndef HAVE_STRSIGNAL
1688
Roland McGrath8f474e02003-01-14 07:53:33 +00001689#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
Roland McGrath6d2b3492002-12-30 00:51:30 +00001690extern char *sys_siglist[];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691#endif
Roland McGrath8f474e02003-01-14 07:53:33 +00001692#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
1693extern char *_sys_siglist[];
1694#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695
1696const char *
Denys Vlasenko12014262011-05-30 14:00:14 +02001697strsignal(int sig)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001698{
Denys Vlasenko1945ccc2012-02-27 14:37:48 +01001699 static char buf[sizeof("Unknown signal %d") + sizeof(int)*3];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001700
1701 if (sig < 1 || sig >= NSIG) {
1702 sprintf(buf, "Unknown signal %d", sig);
1703 return buf;
1704 }
1705#ifdef HAVE__SYS_SIGLIST
1706 return _sys_siglist[sig];
1707#else
1708 return sys_siglist[sig];
1709#endif
1710}
1711
1712#endif /* HAVE_STRSIGNAL */
1713
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714static int
Denys Vlasenko12014262011-05-30 14:00:14 +02001715trace(void)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001717 struct rusage ru;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001718 struct rusage *rup = cflag ? &ru : NULL;
1719# ifdef __WALL
Roland McGratheb9e2e82009-06-02 16:49:22 -07001720 static int wait4_options = __WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001721# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722
Roland McGratheb9e2e82009-06-02 16:49:22 -07001723 while (nprocs != 0) {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001724 int pid;
1725 int wait_errno;
1726 int status, sig;
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001727 int stopped;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001728 struct tcb *tcp;
1729 unsigned event;
1730
Denys Vlasenko222713a2009-03-17 14:29:59 +00001731 if (interrupted)
Roland McGratheb9e2e82009-06-02 16:49:22 -07001732 return 0;
1733 if (interactive)
1734 sigprocmask(SIG_SETMASK, &empty_set, NULL);
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001735# ifdef __WALL
1736 pid = wait4(-1, &status, wait4_options, rup);
Roland McGrath5bc05552002-12-17 04:50:47 +00001737 if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001738 /* this kernel does not support __WALL */
1739 wait4_options &= ~__WALL;
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001740 pid = wait4(-1, &status, wait4_options, rup);
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001741 }
Roland McGrath5bc05552002-12-17 04:50:47 +00001742 if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001743 /* most likely a "cloned" process */
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001744 pid = wait4(-1, &status, __WCLONE, rup);
1745 if (pid < 0) {
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001746 perror_msg("wait4(__WCLONE) failed");
Wichert Akkerman2f1d87e2001-03-28 14:40:14 +00001747 }
1748 }
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001749# else
1750 pid = wait4(-1, &status, 0, rup);
1751# endif /* __WALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001752 wait_errno = errno;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001753 if (interactive)
1754 sigprocmask(SIG_BLOCK, &blocked_set, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755
Denys Vlasenko26d1b1e2011-08-15 12:24:14 +02001756 if (pid < 0) {
Roland McGratheb9e2e82009-06-02 16:49:22 -07001757 switch (wait_errno) {
1758 case EINTR:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001759 continue;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001760 case ECHILD:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761 /*
1762 * We would like to verify this case
1763 * but sometimes a race in Solbourne's
1764 * version of SunOS sometimes reports
1765 * ECHILD before sending us SIGCHILD.
1766 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001767 return 0;
1768 default:
1769 errno = wait_errno;
Denys Vlasenko4c65c442012-03-08 11:54:10 +01001770 perror_msg("wait");
Roland McGratheb9e2e82009-06-02 16:49:22 -07001771 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 }
1773 }
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001774 if (pid == popen_pid) {
1775 if (WIFEXITED(status) || WIFSIGNALED(status))
Denys Vlasenko7dd23382011-06-22 13:03:56 +02001776 popen_pid = 0;
Dmitry V. Levin10de62b2006-12-13 21:45:31 +00001777 continue;
1778 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001779
1780 event = ((unsigned)status >> 16);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001781 if (debug) {
1782 char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001783 if (event != 0) {
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001784 static const char *const event_names[] = {
1785 [PTRACE_EVENT_CLONE] = "CLONE",
1786 [PTRACE_EVENT_FORK] = "FORK",
1787 [PTRACE_EVENT_VFORK] = "VFORK",
1788 [PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
1789 [PTRACE_EVENT_EXEC] = "EXEC",
1790 [PTRACE_EVENT_EXIT] = "EXIT",
1791 };
1792 const char *e;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001793 if (event < ARRAY_SIZE(event_names))
1794 e = event_names[event];
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001795 else {
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001796 sprintf(buf, "?? (%u)", event);
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001797 e = buf;
1798 }
1799 fprintf(stderr, " PTRACE_EVENT_%s", e);
1800 }
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001801 strcpy(buf, "???");
1802 if (WIFSIGNALED(status))
1803#ifdef WCOREDUMP
1804 sprintf(buf, "WIFSIGNALED,%ssig=%s",
1805 WCOREDUMP(status) ? "core," : "",
1806 signame(WTERMSIG(status)));
1807#else
1808 sprintf(buf, "WIFSIGNALED,sig=%s",
1809 signame(WTERMSIG(status)));
1810#endif
1811 if (WIFEXITED(status))
1812 sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
1813 if (WIFSTOPPED(status))
1814 sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001815#ifdef WIFCONTINUED
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001816 if (WIFCONTINUED(status))
1817 strcpy(buf, "WIFCONTINUED");
Denys Vlasenko5bd67c82011-08-15 11:36:09 +02001818#endif
Denys Vlasenko1d5f12e2011-06-24 16:41:35 +02001819 fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
1820 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001822 /* Look up 'pid' in our table. */
Denys Vlasenko5d645812011-08-20 12:48:18 +02001823 tcp = pid2tcb(pid);
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001824
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001825 /* Under Linux, execve changes pid to thread leader's pid,
1826 * and we see this changed pid on EVENT_EXEC and later,
1827 * execve sysexit. Leader "disappears" without exit
1828 * notification. Let user know that, drop leader's tcb,
1829 * and fix up pid in execve thread's tcb.
1830 * Effectively, execve thread's tcb replaces leader's tcb.
1831 *
1832 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
1833 * on exit syscall) in multithreaded programs exactly
1834 * in order to handle this case.
1835 *
1836 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
1837 * On 2.6 and earlier, it can return garbage.
1838 */
1839 if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
1840 long old_pid = 0;
1841 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
1842 && old_pid > 0
1843 && old_pid != pid
1844 ) {
1845 struct tcb *execve_thread = pid2tcb(old_pid);
1846 if (tcp) {
1847 outf = tcp->outf;
1848 curcol = tcp->curcol;
1849 if (!cflag) {
Denys Vlasenko000b6012012-01-28 01:25:03 +01001850 if (printing_tcp)
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001851 tprints(" <unfinished ...>\n");
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001852 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001853 tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
1854 printing_tcp = NULL;
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001855 fflush(outf);
1856 }
1857 if (execve_thread) {
1858 /* swap output FILEs (needed for -ff) */
1859 tcp->outf = execve_thread->outf;
1860 execve_thread->outf = outf;
1861 }
1862 droptcb(tcp);
1863 }
1864 tcp = execve_thread;
1865 if (tcp) {
1866 tcp->pid = pid;
1867 tcp->flags |= TCB_REPRINT;
1868 }
1869 }
1870 }
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001871
Denys Vlasenko5d645812011-08-20 12:48:18 +02001872 if (tcp == NULL) {
Roland McGrath41c48222008-07-18 00:25:10 +00001873 if (followfork) {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001874 /* This is needed to go with the CLONE_PTRACE
1875 changes in process.c/util.c: we might see
1876 the child's initial trap before we see the
1877 parent return from the clone syscall.
1878 Leave the child suspended until the parent
1879 returns from its system call. Only then
1880 will we have the association of parent and
1881 child so that we know how to do clearbpt
1882 in the child. */
Denys Vlasenko418d66a2009-01-17 01:52:54 +00001883 tcp = alloctcb(pid);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001884 tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001885 if (!qflag)
Denys Vlasenko833fb132011-08-17 11:30:56 +02001886 fprintf(stderr, "Process %d attached\n",
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001887 pid);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001888 }
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001889 else
1890 /* This can happen if a clone call used
1891 CLONE_PTRACE itself. */
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001892 {
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001893 if (WIFSTOPPED(status))
Denys Vlasenko97c503f2012-03-09 15:11:21 +01001894 ptrace(PTRACE_CONT, pid, (char *) 0, 0);
Denys Vlasenkocb2ad002011-06-23 13:05:29 +02001895 error_msg_and_die("Unknown pid: %u", pid);
Roland McGrathe85bbfe2003-01-09 06:53:31 +00001896 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001897 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001898 /* set current output file */
1899 outf = tcp->outf;
Andreas Schwabccdff482009-10-27 16:27:13 +01001900 curcol = tcp->curcol;
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001901 if (cflag) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1903 tcp->stime = ru.ru_stime;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001904 }
Roland McGratheb9e2e82009-06-02 16:49:22 -07001905
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001906 if (WIFSIGNALED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001907 if (pid == strace_child)
1908 exit_code = 0x100 | WTERMSIG(status);
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00001909 if (cflag != CFLAG_ONLY_STATS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910 && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1911 printleader(tcp);
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001912#ifdef WCOREDUMP
Denys Vlasenko000b6012012-01-28 01:25:03 +01001913 tprintf("+++ killed by %s %s+++\n",
Roland McGrath2efe8792004-01-13 09:59:45 +00001914 signame(WTERMSIG(status)),
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001915 WCOREDUMP(status) ? "(core dumped) " : "");
1916#else
Denys Vlasenko000b6012012-01-28 01:25:03 +01001917 tprintf("+++ killed by %s +++\n",
Denys Vlasenko13d22f12011-06-24 23:01:57 +02001918 signame(WTERMSIG(status)));
Roland McGrath2efe8792004-01-13 09:59:45 +00001919#endif
Denys Vlasenko000b6012012-01-28 01:25:03 +01001920 printing_tcp = NULL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001921 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001922 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923 droptcb(tcp);
1924 continue;
1925 }
1926 if (WIFEXITED(status)) {
Dmitry V. Levina6809652008-11-10 17:14:58 +00001927 if (pid == strace_child)
1928 exit_code = WEXITSTATUS(status);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001929 if (tcp == printing_tcp) {
1930 tprints(" <unfinished ...>\n");
1931 printing_tcp = NULL;
Roland McGrath0a396902003-06-10 03:05:53 +00001932 }
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001933 if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
1934 printleader(tcp);
Denys Vlasenko000b6012012-01-28 01:25:03 +01001935 tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
1936 printing_tcp = NULL;
Denys Vlasenko19cdada2011-08-17 10:45:32 +02001937 }
Denys Vlasenko5e09d772012-01-18 16:20:56 +01001938 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001939 droptcb(tcp);
1940 continue;
1941 }
1942 if (!WIFSTOPPED(status)) {
1943 fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1944 droptcb(tcp);
1945 continue;
1946 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001947
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001948 /* Is this the very first time we see this tracee stopped? */
1949 if (tcp->flags & TCB_STARTUP) {
1950 if (debug)
1951 fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952 tcp->flags &= ~TCB_STARTUP;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001953 if (tcp->flags & TCB_BPTSET) {
Roland McGrath02203312007-06-11 22:06:31 +00001954 /*
1955 * One example is a breakpoint inherited from
Denys Vlasenko2ecba322011-08-21 17:35:39 +02001956 * parent through fork().
Roland McGrath02203312007-06-11 22:06:31 +00001957 */
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02001958 if (clearbpt(tcp) < 0) {
1959 /* Pretty fatal */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001960 droptcb(tcp);
1961 cleanup();
1962 return -1;
1963 }
1964 }
Denys Vlasenko44f87ef2011-08-17 15:18:21 +02001965 if (ptrace_setoptions) {
1966 if (debug)
1967 fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
1968 if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
1969 if (errno != ESRCH) {
1970 /* Should never happen, really */
1971 perror_msg_and_die("PTRACE_SETOPTIONS");
Denys Vlasenko3454e4b2011-05-23 21:29:03 +02001972 }
1973 }
1974 }
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001975 }
1976
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001977 sig = WSTOPSIG(status);
1978
Denys Vlasenkof7db5dd2012-01-28 01:16:02 +01001979 if (event != 0) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001980 /* Ptrace event */
1981#ifdef USE_SEIZE
1982 if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
Denys Vlasenko67038162012-01-29 16:46:46 +01001983 /*
1984 * PTRACE_INTERRUPT-stop or group-stop.
1985 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
1986 */
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01001987 if (sig == SIGSTOP
1988 || sig == SIGTSTP
1989 || sig == SIGTTIN
1990 || sig == SIGTTOU
1991 ) {
1992 stopped = 1;
1993 goto show_stopsig;
1994 }
1995 }
1996#endif
Denys Vlasenkof88837a2011-09-05 14:05:46 +02001997 goto restart_tracee_with_sig_0;
1998 }
1999
Denys Vlasenkof88837a2011-09-05 14:05:46 +02002000 /* Is this post-attach SIGSTOP?
2001 * Interestingly, the process may stop
2002 * with STOPSIG equal to some other signal
2003 * than SIGSTOP if we happend to attach
2004 * just before the process takes a signal.
2005 */
2006 if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2007 if (debug)
2008 fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2009 tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002010 goto restart_tracee_with_sig_0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002011 }
2012
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002013 if (sig != syscall_trap_sig) {
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002014 siginfo_t si;
2015
2016 /* Nonzero (true) if tracee is stopped by signal
2017 * (as opposed to "tracee received signal").
2018 */
2019 stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
Denys Vlasenko67038162012-01-29 16:46:46 +01002020#ifdef USE_SEIZE
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002021 show_stopsig:
Denys Vlasenko67038162012-01-29 16:46:46 +01002022#endif
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002023 if (cflag != CFLAG_ONLY_STATS
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002024 && (qual_flags[sig] & QUAL_SIGNAL)) {
Dmitry V. Levinc15dfc72011-03-10 14:44:45 +00002025#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002026 long pc = 0;
2027 long psr = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002028
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002029 upeek(tcp, PT_CR_IPSR, &psr);
2030 upeek(tcp, PT_CR_IIP, &pc);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002031
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002032# define PSR_RI 41
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002033 pc += (psr >> PSR_RI) & 0x3;
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002034# define PC_FORMAT_STR " @ %lx"
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002035# define PC_FORMAT_ARG , pc
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002036#else
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002037# define PC_FORMAT_STR ""
2038# define PC_FORMAT_ARG /* nothing */
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002039#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 printleader(tcp);
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002041 if (!stopped) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002042 tprints("--- ");
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002043 printsiginfo(&si, verbose(tcp));
Denys Vlasenko000b6012012-01-28 01:25:03 +01002044 tprintf(" (%s)" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002045 strsignal(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002046 PC_FORMAT_ARG);
2047 } else
Denys Vlasenko000b6012012-01-28 01:25:03 +01002048 tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002049 strsignal(sig),
2050 signame(sig)
Dmitry V. Levin6b7a2612011-03-10 21:20:35 +00002051 PC_FORMAT_ARG);
Denys Vlasenko000b6012012-01-28 01:25:03 +01002052 printing_tcp = NULL;
Denys Vlasenko5e09d772012-01-18 16:20:56 +01002053 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002054 }
Denys Vlasenko31fa8a22012-01-29 02:01:44 +01002055
2056 if (!stopped)
2057 /* It's signal-delivery-stop. Inject the signal */
2058 goto restart_tracee;
2059
2060 /* It's group-stop */
2061#ifdef USE_SEIZE
2062 if (use_seize) {
2063 /*
2064 * This ends ptrace-stop, but does *not* end group-stop.
2065 * This makes stopping signals work properly on straced process
2066 * (that is, process really stops. It used to continue to run).
2067 */
2068 if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
2069 cleanup();
2070 return -1;
2071 }
2072 continue;
2073 }
2074 /* We don't have PTRACE_LISTEN support... */
2075#endif
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002076 goto restart_tracee;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002077 }
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002078
2079 /* We handled quick cases, we are permitted to interrupt now. */
Roland McGrath02203312007-06-11 22:06:31 +00002080 if (interrupted)
2081 return 0;
Denys Vlasenko2ecba322011-08-21 17:35:39 +02002082
2083 /* This should be syscall entry or exit.
2084 * (Or it still can be that pesky post-execve SIGTRAP!)
2085 * Handle it.
2086 */
Roland McGratheb9e2e82009-06-02 16:49:22 -07002087 if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2088 /* ptrace() failed in trace_syscall() with ESRCH.
2089 * Likely a result of process disappearing mid-flight.
2090 * Observed case: exit_group() terminating
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002091 * all processes in thread group.
Denys Vlasenkoef2fbf82009-01-06 21:45:06 +00002092 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002093 if (printing_tcp) {
2094 /* Do we have dangling line "syscall(param, param"?
2095 * Finish the line then.
Denys Vlasenkof1e69032012-01-04 15:15:26 +01002096 */
Denys Vlasenkof2025022012-03-09 15:29:45 +01002097 printing_tcp->flags |= TCB_REPRINT;
2098 tprints(" <unfinished ...>\n");
2099 printing_tcp = NULL;
2100 fflush(tcp->outf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101 }
Denys Vlasenkof2025022012-03-09 15:29:45 +01002102 /* We assume that ptrace error was caused by process death.
2103 * We used to detach(tcp) here, but since we no longer
2104 * implement "detach before death" policy/hack,
2105 * we can let this process to report its death to us
2106 * normally, via WIFEXITED or WIFSIGNALED wait status.
2107 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002108 continue;
2109 }
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002110 restart_tracee_with_sig_0:
2111 sig = 0;
2112 restart_tracee:
Andreas Schwabccdff482009-10-27 16:27:13 +01002113 /* Remember current print column before continuing. */
2114 tcp->curcol = curcol;
Denys Vlasenko6cda73f2011-09-02 16:23:53 +02002115 if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 cleanup();
2117 return -1;
2118 }
2119 }
2120 return 0;
2121}
Denys Vlasenkoecc8b972012-03-12 23:05:25 +01002122
2123int
2124main(int argc, char *argv[])
2125{
2126 init(argc, argv);
2127
2128 /* Run main tracing loop */
2129 if (trace() < 0)
2130 return 1;
2131
2132 cleanup();
2133 fflush(NULL);
2134 if (exit_code > 0xff) {
2135 /* Avoid potential core file clobbering. */
2136 struct rlimit rlim = {0, 0};
2137 setrlimit(RLIMIT_CORE, &rlim);
2138
2139 /* Child was killed by a signal, mimic that. */
2140 exit_code &= 0xff;
2141 signal(exit_code, SIG_DFL);
2142 raise(exit_code);
2143 /* Paranoia - what if this signal is not fatal?
2144 Exit with 128 + signo then. */
2145 exit_code += 128;
2146 }
2147
2148 return exit_code;
2149}